<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>jdk8 新特性.md | 小波的博客</title><meta name="keywords" content="JAVA"><meta name="author" content="Steve"><meta name="copyright" content="Steve"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="jdk8 新特性">
<meta property="og:type" content="article">
<meta property="og:title" content="jdk8 新特性.md">
<meta property="og:url" content="https://steve6636.gitee.io/2022/03/06/Junit&jdk8%E6%96%B0%E7%89%B9%E6%80%A7/index.html">
<meta property="og:site_name" content="小波的博客">
<meta property="og:description" content="jdk8 新特性">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.05sun.com%2Fup%2F2006%2F2020611101156542640.png&refer=http%3A%2F%2Fimg.05sun.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1649170568&t=1d3529a6cb00dac37673cce4473d9a89">
<meta property="article:published_time" content="2022-03-06T14:47:18.000Z">
<meta property="article:modified_time" content="2022-03-06T14:56:48.857Z">
<meta property="article:author" content="Steve">
<meta property="article:tag" content="JAVA">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.05sun.com%2Fup%2F2006%2F2020611101156542640.png&refer=http%3A%2F%2Fimg.05sun.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1649170568&t=1d3529a6cb00dac37673cce4473d9a89"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://steve6636.gitee.io/2022/03/06/Junit&amp;jdk8%E6%96%B0%E7%89%B9%E6%80%A7/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"search.xml","languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'mediumZoom',
  Snackbar: undefined,
  source: {
    jQuery: 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isanchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = { 
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2022-03-06 22:56:48'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const fontSizeVal = saveToLocal.get('global-font-size')
    if (fontSizeVal !== undefined) {
      document.documentElement.style.setProperty('--global-font-size', fontSizeVal + 'px')
    }
    })(window)</script><meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/atom.xml" title="小波的博客" type="application/atom+xml">
</head><body><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="author-avatar"><img class="avatar-img" data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20210327175316.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/archives/"><div class="headline">文章</div><div class="length-num">26</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/tags/"><div class="headline">标签</div><div class="length-num">11</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/categories/"><div class="headline">分类</div><div class="length-num">9</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> Link</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于我</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 工具箱</span></a></div><div class="menus_item"><a class="site-page" href="/friends"><i class="fa-fw fas fa-address-book"></i><span> Friends</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.05sun.com%2Fup%2F2006%2F2020611101156542640.png&amp;refer=http%3A%2F%2Fimg.05sun.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1649170568&amp;t=1d3529a6cb00dac37673cce4473d9a89')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">小波的博客</a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> Link</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于我</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 工具箱</span></a></div><div class="menus_item"><a class="site-page" href="/friends"><i class="fa-fw fas fa-address-book"></i><span> Friends</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">jdk8 新特性.md</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2022-03-06T14:47:18.000Z" title="发表于 2022-03-06 22:47:18">2022-03-06</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-03-06T14:56:48.857Z" title="更新于 2022-03-06 22:56:48">2022-03-06</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/JAVA/">JAVA</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">13.4k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>54分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h1 id="Junit-amp-jdk8-新特性"><a href="#Junit-amp-jdk8-新特性" class="headerlink" title="Junit&amp;jdk8 新特性"></a>Junit&amp;jdk8 新特性</h1><h2 id="第一章-Junit"><a href="#第一章-Junit" class="headerlink" title="第一章 Junit"></a>第一章 Junit</h2><h3 id="1-学习目标"><a href="#1-学习目标" class="headerlink" title="1. 学习目标"></a>1. 学习目标</h3><ul>
<li>了解 Junit 的概述</li>
<li>掌握 Junit 的使用</li>
</ul>
<h3 id="2-内容讲解"><a href="#2-内容讲解" class="headerlink" title="2. 内容讲解"></a>2. 内容讲解</h3><h4 id="2-1-Junit-是什么"><a href="#2-1-Junit-是什么" class="headerlink" title="2.1 Junit 是什么"></a>2.1 Junit 是什么</h4><p>Junit 是 Java 语言编写的第三方单元测试框架</p>
<h4 id="2-2-单元测试概念"><a href="#2-2-单元测试概念" class="headerlink" title="2.2 单元测试概念"></a>2.2 单元测试概念</h4><ul>
<li>单元：在 Java 中，一个类就是一个单元</li>
<li>单元测试：程序猿编写的一小段代码，用来对某个类中的某个方法进行功能测试或业务逻辑测试。</li>
</ul>
<h4 id="2-3-Junit-单元测试框架的作用"><a href="#2-3-Junit-单元测试框架的作用" class="headerlink" title="2.3 Junit 单元测试框架的作用"></a>2.3 Junit 单元测试框架的作用</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">用来对类中的方法功能进行有目的的测试，以保证程序的正确性和稳定性。</span><br><span class="line">能够让方法独立运行起来。</span><br></pre></td></tr></table></figure>

<h4 id="2-4-Junit-单元测试框架的使用步骤"><a href="#2-4-Junit-单元测试框架的使用步骤" class="headerlink" title="2.4 Junit 单元测试框架的使用步骤"></a>2.4 Junit 单元测试框架的使用步骤</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">编写业务类，在业务类中编写业务方法。比如增删改查的方法</span><br><span class="line">编写测试类，在测试类中编写测试方法，在测试方法中编写测试代码来测试。</span><br><span class="line"> 	测试类的命名规范：以 Test 开头，以业务类类名结尾，使用驼峰命名法</span><br><span class="line">        每一个单词首字母大写，称为大驼峰命名法，比如类名，接口名...</span><br><span class="line">        从第二单词开始首字母大写，称为小驼峰命名法，比如方法命名</span><br><span class="line">        比如业务类类名：ProductDao，那么测试类类名就应该叫：TestProductDao</span><br><span class="line">    测试方法的命名规则：以 test 开头，以业务方法名结尾</span><br><span class="line">        比如业务方法名为：save，那么测试方法名就应该叫：testSave</span><br></pre></td></tr></table></figure>

<h4 id="2-5-测试方法注意事项"><a href="#2-5-测试方法注意事项" class="headerlink" title="2.5 测试方法注意事项"></a>2.5 测试方法注意事项</h4><ul>
<li>必须是 public 修饰的，没有返回值，没有参数</li>
<li>必须使注解 @Test 修饰</li>
</ul>
<h4 id="2-6-如何运行测试方法"><a href="#2-6-如何运行测试方法" class="headerlink" title="2.6 如何运行测试方法"></a>2.6 如何运行测试方法</h4><ul>
<li>选中方法名 –&gt; 右键 –&gt; Run ‘测试方法名’  运行选中的测试方法</li>
<li>选中测试类类名 –&gt; 右键 –&gt; Run ‘测试类类名’  运行测试类中所有测试方法</li>
<li>选中模块名 –&gt; 右键 –&gt; Run ‘All Tests’  运行模块中的所有测试类的所有测试方法</li>
</ul>
<h4 id="2-7-如何查看测试结果"><a href="#2-7-如何查看测试结果" class="headerlink" title="2.7 如何查看测试结果"></a>2.7 如何查看测试结果</h4><ul>
<li>绿色：表示测试通过</li>
<li>红色：表示测试失败，有问题</li>
</ul>
<h4 id="2-8-Junit-常用注解-Junit4-xxxx-版本"><a href="#2-8-Junit-常用注解-Junit4-xxxx-版本" class="headerlink" title="2.8 Junit 常用注解(Junit4.xxxx 版本)"></a>2.8 Junit 常用注解(Junit4.xxxx 版本)</h4><ul>
<li>@Before：用来修饰方法，该方法会在每一个测试方法执行之前执行一次。</li>
<li>@After：用来修饰方法，该方法会在每一个测试方法执行之后执行一次。</li>
<li>@BeforeClass：用来静态修饰方法，该方法会在所有测试方法之前执行一次。</li>
<li>@AfterClass：用来静态修饰方法，该方法会在所有测试方法之后执行一次。</li>
</ul>
<h4 id="2-9-Junit-常用注解-Junit5-xxxx-版本"><a href="#2-9-Junit-常用注解-Junit5-xxxx-版本" class="headerlink" title="2.9 Junit 常用注解(Junit5.xxxx 版本)"></a>2.9 Junit 常用注解(Junit5.xxxx 版本)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@BeforeEach</span>：用来修饰方法，该方法会在每一个测试方法执行之前执行一次。</span><br><span class="line"><span class="meta">@AfterEach</span>：用来修饰方法，该方法会在每一个测试方法执行之后执行一次。</span><br><span class="line"><span class="meta">@BeforeAll</span>：用来静态修饰方法，该方法会在所有测试方法之前执行一次。</span><br><span class="line"><span class="meta">@AfterAll</span>：用来静态修饰方法，该方法会在所有测试方法之后执行一次。</span><br></pre></td></tr></table></figure>

<h4 id="2-10-Junit-的使用"><a href="#2-10-Junit-的使用" class="headerlink" title="2.10 Junit 的使用"></a>2.10 Junit 的使用</h4><ul>
<li>示例代码</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> 业务类：实现加减乘除运算</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Cacluate</span> </span>&#123;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     业务方法 1：求 a 和 b 之和</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">sum</span><span class="params">(<span class="keyword">int</span> a，<span class="keyword">int</span> b)</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span>  a + b + <span class="number">10</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     业务方法 2: 求 a 和 b 之差</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">sub</span><span class="params">(<span class="keyword">int</span> a，<span class="keyword">int</span> b)</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span>  a - b;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestCacluate</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> Cacluate c = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@BeforeClass</span> <span class="comment">// 用来静态修饰方法，该方法会在所有测试方法之前执行一次。</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;初始化操作&quot;</span>);</span><br><span class="line">        <span class="comment">// 创建 Cacluate 对象</span></span><br><span class="line">        c = <span class="keyword">new</span> Cacluate();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterClass</span> <span class="comment">// 用来静态修饰方法，该方法会在所有测试方法之后执行一次。</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">close</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;释放资源&quot;</span>);</span><br><span class="line">        c = <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">/*@Before // 用来修饰方法，该方法会在每一个测试方法执行之前执行一次。</span></span><br><span class="line"><span class="comment">    public void init()&#123;</span></span><br><span class="line"><span class="comment">        System.out.println(&quot;初始化操作&quot;);</span></span><br><span class="line"><span class="comment">        // 创建 Cacluate 对象</span></span><br><span class="line"><span class="comment">        c = new Cacluate();</span></span><br><span class="line"><span class="comment">    &#125;</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    @After // 用来修饰方法，该方法会在每一个测试方法执行之后执行一次。</span></span><br><span class="line"><span class="comment">    public void close()&#123;</span></span><br><span class="line"><span class="comment">        System.out.println(&quot;释放资源&quot;);</span></span><br><span class="line"><span class="comment">        c = null;</span></span><br><span class="line"><span class="comment">    &#125;*/</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSum</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">int</span> result = c.sum(<span class="number">1</span>，<span class="number">1</span>);</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">            断言：预习判断某个条件一定成立，如果条件不成立，则直接奔溃。</span></span><br><span class="line"><span class="comment">            assertEquals 方法的参数</span></span><br><span class="line"><span class="comment">            (String message， double expected， double actual)</span></span><br><span class="line"><span class="comment">            message： 消息字符串</span></span><br><span class="line"><span class="comment">            expected: 期望值</span></span><br><span class="line"><span class="comment">            actual: 实际值</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="comment">// 如果期望值和实际值一致，则什么也不发生，否则会直接奔溃。</span></span><br><span class="line">        Assert.assertEquals(<span class="string">&quot;期望值和实际值不一致&quot;</span>，<span class="number">12</span>，result);</span><br><span class="line">        System.out.println(result);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSub</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">// 创建 Cacluate 对象</span></span><br><span class="line">        <span class="comment">// Cacluate c = new Cacluate();</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> result = c.sub(<span class="number">1</span>，<span class="number">1</span>);</span><br><span class="line">        <span class="comment">// 如果期望值和实际值一致，则什么也不发生，否则会直接奔溃。</span></span><br><span class="line">        Assert.assertEquals(<span class="string">&quot;期望值和实际值不一致&quot;</span>，<span class="number">0</span>，result);</span><br><span class="line">        System.out.println(result);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="第二章-Lambda-表达式"><a href="#第二章-Lambda-表达式" class="headerlink" title="第二章 Lambda 表达式"></a>第二章 Lambda 表达式</h2><h3 id="1-学习目标-1"><a href="#1-学习目标-1" class="headerlink" title="1. 学习目标"></a>1. 学习目标</h3><ul>
<li><p>能够理解函数式编程相对于面向对象的优点</p>
</li>
<li><p>能够掌握 Lambda 表达式的标准格式</p>
</li>
<li><p>能够使用 Lambda 标准格式</p>
</li>
<li><p>能够掌握 Lambda 表达式的省略格式与规则</p>
</li>
<li><p>能够通过 Lambda 使用自定义的接口（有且仅有一个抽象方法）</p>
</li>
<li><p>能够使用 Supplier 函数式接口</p>
</li>
<li><p>能够使用 Consumer 函数式接口</p>
</li>
<li><p>能够使用 Function 函数式接口</p>
</li>
<li><p>能够使用 Predicate 函数式接口</p>
</li>
<li><p>能够使用方法引用和构造器引用</p>
</li>
</ul>
<h3 id="2-内容讲解-1"><a href="#2-内容讲解-1" class="headerlink" title="2. 内容讲解"></a>2. 内容讲解</h3><h4 id="2-1-函数式编程的优势"><a href="#2-1-函数式编程的优势" class="headerlink" title="2.1 函数式编程的优势"></a>2.1 函数式编程的优势</h4><h5 id="2-1-1-函数式编程思想"><a href="#2-1-1-函数式编程思想" class="headerlink" title="2.1.1 函数式编程思想"></a>2.1.1 函数式编程思想</h5><p><img src= "/img/loading.gif" data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20211024222521.png"></p>
<p>在数学中，**函数 <strong>就是有输入量、输出量的一套计算方案，也就是“拿什么东西做什么事情”。编程中的函数，也有类似的概念，你调用我的时候，给我实参为形参赋值，然后通过运行方法体，给你返回一个结果。对于调用者来做，关注这个方法具备什么样的功能。相对而言，面向对象过分强调“必须通过对象的形式来做事情”，而函数式思想则尽量忽略面向对象的复杂语法——</strong>强调做什么，而不是以什么形式做 **。</p>
<ul>
<li><p>面向对象的思想:</p>
<ul>
<li>做一件事情，找一个能解决这个事情的对象，调用对象的方法，完成事情。</li>
</ul>
</li>
<li><p>函数式编程思想:</p>
<ul>
<li>只要能获取到结果，谁去做的不重要，重视的是结果，不重视过程。</li>
</ul>
</li>
</ul>
<p>Java8 引入了 Lambda 表达式之后，Java 也开始支持函数式编程。</p>
<p>Lambda 表达式不是 Java 最早使用的，很多语言就支持 Lambda 表达式，例如：C++，C#，Python，Scala 等。如果有 Python 或者 Javascript 的语言基础，对理解 Lambda 表达式有很大帮助，可以这么说 lambda 表达式其实就是实现 SAM 接口的语法糖，使得 Java 也算是支持函数式编程的语言。Lambda**写的好 **可以极大的减少代码冗余，同时可读性也好过冗长的匿名内部类。</p>
<blockquote>
<p>备注：“语法糖”是指使用更加方便，但是原理不变的代码语法。例如在遍历集合时使用的 for-each 语法，其实<br>底层的实现原理仍然是迭代器，这便是“语法糖”。从应用层面来讲，Java 中的 Lambda 可以被当做是匿名内部类的“语法糖”，但是二者在原理上是不同的。</p>
</blockquote>
<h5 id="2-2，2-冗余的匿名内部类"><a href="#2-2，2-冗余的匿名内部类" class="headerlink" title="2.2，2 冗余的匿名内部类"></a>2.2，2 冗余的匿名内部类</h5><p>当需要启动一个线程去完成任务时，通常会通过 <code>java.lang.Runnable</code> 接口来定义任务内容，并使用 <code>java.lang.Thread</code> 类来启动该线程。代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo01Runnable</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    	<span class="comment">// 匿名内部类</span></span><br><span class="line">		Runnable task = <span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">			<span class="meta">@Override</span></span><br><span class="line">			<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123; <span class="comment">// 覆盖重写抽象方法</span></span><br><span class="line">				System.out.println(<span class="string">&quot;多线程任务执行！&quot;</span>);</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;;</span><br><span class="line">		<span class="keyword">new</span> Thread(task).start(); <span class="comment">// 启动线程</span></span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>本着 “一切皆对象” 的思想，这种做法是无可厚非的：首先创建一个 <code>Runnable</code> 接口的匿名内部类对象来指定任务内容，再将其交给一个线程来启动。</p>
<p><strong>代码分析：</strong></p>
<p>对于 <code>Runnable</code> 的匿名内部类用法，可以分析出几点内容：</p>
<ul>
<li><code>Thread</code> 类需要 <code>Runnable</code> 接口作为参数，其中的抽象 <code>run</code> 方法是用来指定线程任务内容的核心；</li>
<li>为了指定 <code>run</code> 的方法体，**不得不 **需要 <code>Runnable</code> 接口的实现类；</li>
<li>为了省去定义一个 <code>RunnableImpl</code> 实现类的麻烦，**不得不 **使用匿名内部类；</li>
<li>必须覆盖重写抽象 <code>run</code> 方法，所以方法名称、方法参数、方法返回值 **不得不 **再写一遍，且不能写错；</li>
<li>而实际上，**似乎只有方法体才是关键所在 **。</li>
</ul>
<h5 id="2-1-3-编程思想转换"><a href="#2-1-3-编程思想转换" class="headerlink" title="2.1.3 编程思想转换"></a>2.1.3 编程思想转换</h5><p>**做什么，而不是谁来做，怎么做 **</p>
<p>我们真的希望创建一个匿名内部类对象吗？不。我们只是为了做这件事情而 **不得不 **创建一个对象。我们真正希望做的事情是：将 <code>run</code> 方法体内的代码传递给 <code>Thread</code> 类知晓。</p>
<p>**传递一段代码 **——这才是我们真正的目的。而创建对象只是受限于面向对象语法而不得不采取的一种手段方式。那，有没有更加简单的办法？如果我们将关注点从 “怎么做” 回归到 “做什么” 的本质上，就会发现只要能够更好地达到目的，过程与形式其实并不重要。</p>
<p><strong>生活举例：</strong></p>
<p><img src= "/img/loading.gif" data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20211024222525.png"></p>
<p>当我们需要从北京到上海时，可以选择高铁、汽车、骑行或是徒步。我们的真正目的是到达上海，而如何才能到达上海的形式并不重要，所以我们一直在探索有没有比高铁更好的方式——搭乘飞机。</p>
<p><img src= "/img/loading.gif" data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20211024222527.png"></p>
<p>而现在这种飞机（甚至是飞船）已经诞生：2014 年 3 月 Oracle 所发布的 Java 8（JDK 1.8）中，加入了 **Lambda 表达式 **的重量级新特性，为我们打开了新世界的大门。</p>
<h5 id="2-1-4-体验-Lambda-的更优写法"><a href="#2-1-4-体验-Lambda-的更优写法" class="headerlink" title="2.1.4 体验 Lambda 的更优写法"></a>2.1.4 体验 Lambda 的更优写法</h5><p>借助 Java 8 的全新语法，上述 <code>Runnable</code> 接口的匿名内部类写法可以通过更简单的 Lambda 表达式达到等效：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo02LambdaRunnable</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">new</span> Thread(() -&gt; System.out.println(<span class="string">&quot;多线程任务执行！&quot;</span>)).start(); <span class="comment">// 启动线程</span></span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这段代码和刚才的执行效果是完全一样的，可以在 1.8 或更高的编译级别下通过。从代码的语义中可以看出：我们启动了一个线程，而线程任务的内容以一种更加简洁的形式被指定。</p>
<p>不再有 “不得不创建接口对象” 的束缚，不再有 “抽象方法覆盖重写” 的负担，就是这么简单！</p>
<h4 id="2-2-函数式接口"><a href="#2-2-函数式接口" class="headerlink" title="2.2 函数式接口"></a>2.2 函数式接口</h4><p>lambda 表达式其实就是实现 SAM 接口的语法糖，所谓 SAM 接口就是 Single Abstract Method，即该接口中只有一个抽象方法需要实现，当然该接口可以包含其他非抽象方法。</p>
<p>其实只要<strong>满足 “SAM” 特征的接口都可以称为函数式接口</strong>，都可以使用 Lambda 表达式，但是如果要更明确一点，最好在声明接口时，加上 @FunctionalInterface。一旦使用该注解来定义接口，编译器将会强制检查该接口是否确实有且仅有一个抽象方法，否则将会报错。</p>
<p>之前学过的 SAM 接口中，标记了 @FunctionalInterface 的函数式接口的有：Runnable，Comparator，FileFilter。</p>
<p>Java8 在 java.util.function 新增了很多函数式接口：主要分为四大类，消费型、供给型、判断型、功能型。基本可以满足我们的开发需求。当然你也可以定义自己的函数式接口。</p>
<h5 id="2-2-1-自定义函数式接口"><a href="#2-2-1-自定义函数式接口" class="headerlink" title="2.2.1 自定义函数式接口"></a>2.2.1 自定义函数式接口</h5><p>只要确保接口中有且仅有一个抽象方法即可：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">修饰符 <span class="class"><span class="keyword">interface</span> 接口名称 </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">abstract</span> 返回值类型 方法名称(可选参数信息);</span><br><span class="line">    <span class="comment">// 其他非抽象方法内容</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>接口当中抽象方法的 public abstract 是可以省略的</p>
</blockquote>
<p>例如：声明一个计算器 <code>Calculator</code> 接口，内含抽象方法 <code>calc</code> 可以对两个 int 数字进行计算，并返回结果：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Calculator</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">calc</span><span class="params">(<span class="keyword">int</span> a， <span class="keyword">int</span> b)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在测试类中，声明一个如下方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">invokeCalc</span><span class="params">(<span class="keyword">int</span> a， <span class="keyword">int</span> b， Calculator calculator)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> result = calculator.calc(a， b);</span><br><span class="line">    System.out.println(<span class="string">&quot;结果是：&quot;</span> + result);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>下面进行测试：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    invokeCalc(<span class="number">1</span>， <span class="number">2</span>， (<span class="keyword">int</span> a，<span class="keyword">int</span> b)-&gt; &#123;<span class="keyword">return</span> a+b;&#125;);</span><br><span class="line">    invokeCalc(<span class="number">1</span>， <span class="number">2</span>， (<span class="keyword">int</span> a，<span class="keyword">int</span> b)-&gt; &#123;<span class="keyword">return</span> a-b;&#125;);</span><br><span class="line">    invokeCalc(<span class="number">1</span>， <span class="number">2</span>， (<span class="keyword">int</span> a，<span class="keyword">int</span> b)-&gt; &#123;<span class="keyword">return</span> a*b;&#125;);</span><br><span class="line">    invokeCalc(<span class="number">1</span>， <span class="number">2</span>， (<span class="keyword">int</span> a，<span class="keyword">int</span> b)-&gt; &#123;<span class="keyword">return</span> a/b;&#125;);</span><br><span class="line">    invokeCalc(<span class="number">1</span>， <span class="number">2</span>， (<span class="keyword">int</span> a，<span class="keyword">int</span> b)-&gt; &#123;<span class="keyword">return</span> a%b;&#125;);</span><br><span class="line">    invokeCalc(<span class="number">1</span>， <span class="number">2</span>， (<span class="keyword">int</span> a，<span class="keyword">int</span> b)-&gt; &#123;<span class="keyword">return</span> a&gt;b?a:b;&#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-2-2-函数式接口的分类"><a href="#2-2-2-函数式接口的分类" class="headerlink" title="2.2.2 函数式接口的分类"></a>2.2.2 函数式接口的分类</h5><p>除了我们可以自定义函数式接口之外，jdk 也给我们内置了一些函数式接口，具体分类如下</p>
<h6 id="2-2-2-1-消费型接口"><a href="#2-2-2-1-消费型接口" class="headerlink" title="2.2.2.1 消费型接口"></a>2.2.2.1 消费型接口</h6><p>消费型接口的抽象方法特点：有形参，但是返回值类型是 void</p>
<table>
<thead>
<tr>
<th>接口名</th>
<th>抽象方法</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td><code>Consumer&lt;T&gt;</code></td>
<td>void accept(T t)</td>
<td>接收一个对象用于完成功能</td>
</tr>
<tr>
<td>BiConsumer&lt;T,U&gt;</td>
<td>void accept(T t, U u)</td>
<td>接收两个对象用于完成功能</td>
</tr>
<tr>
<td>DoubleConsumer</td>
<td>void accept(double value)</td>
<td>接收一个 double 值</td>
</tr>
<tr>
<td>IntConsumer</td>
<td>void accept(int value)</td>
<td>接收一个 int 值</td>
</tr>
<tr>
<td>LongConsumer</td>
<td>void accept(long value)</td>
<td>接收一个 long 值</td>
</tr>
<tr>
<td><code>ObjDoubleConsumer&lt;T&gt;</code></td>
<td>void accept(T t, double value)</td>
<td>接收一个对象和一个 double 值</td>
</tr>
<tr>
<td><code>ObjIntConsumer&lt;T&gt;</code></td>
<td>void accept(T t, int value)</td>
<td>接收一个对象和一个 int 值</td>
</tr>
<tr>
<td><code>ObjLongConsumer&lt;T&gt;</code></td>
<td>void accept(T t, long value)</td>
<td>接收一个对象和一个 long 值</td>
</tr>
</tbody></table>
<h6 id="2-2-2-2-供给型接口"><a href="#2-2-2-2-供给型接口" class="headerlink" title="2.2.2.2 供给型接口"></a>2.2.2.2 供给型接口</h6><p>这类接口的抽象方法特点：无参，但是有返回值</p>
<table>
<thead>
<tr>
<th>接口名</th>
<th>抽象方法</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td><code>Supplier&lt;T&gt;</code></td>
<td>T get()</td>
<td>返回一个对象</td>
</tr>
<tr>
<td>BooleanSupplier</td>
<td>boolean getAsBoolean()</td>
<td>返回一个 boolean 值</td>
</tr>
<tr>
<td>DoubleSupplier</td>
<td>double getAsDouble()</td>
<td>返回一个 double 值</td>
</tr>
<tr>
<td>IntSupplier</td>
<td>int getAsInt()</td>
<td>返回一个 int 值</td>
</tr>
<tr>
<td>LongSupplier</td>
<td>long getAsLong()</td>
<td>返回一个 long 值</td>
</tr>
</tbody></table>
<h6 id="2-2-2-3-断言型接口"><a href="#2-2-2-3-断言型接口" class="headerlink" title="2.2.2.3 断言型接口"></a>2.2.2.3 断言型接口</h6><p>这里接口的抽象方法特点：有参，但是返回值类型是 boolean 结果。</p>
<table>
<thead>
<tr>
<th>接口名</th>
<th>抽象方法</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td><code>Predicate&lt;T&gt;</code></td>
<td>boolean test(T t)</td>
<td>接收一个对象</td>
</tr>
<tr>
<td>BiPredicate&lt;T,U&gt;</td>
<td>boolean test(T t, U u)</td>
<td>接收两个对象</td>
</tr>
<tr>
<td>DoublePredicate</td>
<td>boolean test(double value)</td>
<td>接收一个 double 值</td>
</tr>
<tr>
<td>IntPredicate</td>
<td>boolean test(int value)</td>
<td>接收一个 int 值</td>
</tr>
<tr>
<td>LongPredicate</td>
<td>boolean test(long value)</td>
<td>接收一个 long 值</td>
</tr>
</tbody></table>
<h6 id="2-2-2-4-功能型接口"><a href="#2-2-2-4-功能型接口" class="headerlink" title="2.2.2.4 功能型接口"></a>2.2.2.4 功能型接口</h6><p>这类接口的抽象方法特点：既有参数又有返回值</p>
<table>
<thead>
<tr>
<th>接口名</th>
<th>抽象方法</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>Function&lt;T,R&gt;</td>
<td>R apply(T t)</td>
<td>接收一个 T 类型对象，返回一个 R 类型对象结果</td>
</tr>
<tr>
<td>UnaryOperator<T></td>
<td>T apply(T t)</td>
<td>接收一个 T 类型对象，返回一个 T 类型对象结果</td>
</tr>
<tr>
<td>DoubleFunction<R></td>
<td>R apply(double value)</td>
<td>接收一个 double 值，返回一个 R 类型对象</td>
</tr>
<tr>
<td>IntFunction<R></td>
<td>R apply(int value)</td>
<td>接收一个 int 值，返回一个 R 类型对象</td>
</tr>
<tr>
<td>LongFunction<R></td>
<td>R apply(long value)</td>
<td>接收一个 long 值，返回一个 R 类型对象</td>
</tr>
<tr>
<td>ToDoubleFunction<T></td>
<td>double applyAsDouble(T value)</td>
<td>接收一个 T 类型对象，返回一个 double</td>
</tr>
<tr>
<td><code>ToIntFunction&lt;T&gt;</code></td>
<td>int applyAsInt(T value)</td>
<td>接收一个 T 类型对象，返回一个 int</td>
</tr>
<tr>
<td><code>ToLongFunction&lt;T&gt;</code></td>
<td>long applyAsLong(T value)</td>
<td>接收一个 T 类型对象，返回一个 long</td>
</tr>
<tr>
<td>DoubleToIntFunction</td>
<td>int applyAsInt(double value)</td>
<td>接收一个 double 值，返回一个 int 结果</td>
</tr>
<tr>
<td>DoubleToLongFunction</td>
<td>long applyAsLong(double value)</td>
<td>接收一个 double 值，返回一个 long 结果</td>
</tr>
<tr>
<td>IntToDoubleFunction</td>
<td>double applyAsDouble(int value)</td>
<td>接收一个 int 值，返回一个 double 结果</td>
</tr>
<tr>
<td>IntToLongFunction</td>
<td>long applyAsLong(int value)</td>
<td>接收一个 int 值，返回一个 long 结果</td>
</tr>
<tr>
<td>LongToDoubleFunction</td>
<td>double applyAsDouble(long value)</td>
<td>接收一个 long 值，返回一个 double 结果</td>
</tr>
<tr>
<td>LongToIntFunction</td>
<td>int applyAsInt(long value)</td>
<td>接收一个 long 值，返回一个 int 结果</td>
</tr>
<tr>
<td>DoubleUnaryOperator</td>
<td>double applyAsDouble(double operand)</td>
<td>接收一个 double 值，返回一个 double</td>
</tr>
<tr>
<td>IntUnaryOperator</td>
<td>int applyAsInt(int operand)</td>
<td>接收一个 int 值，返回一个 int 结果</td>
</tr>
<tr>
<td>LongUnaryOperator</td>
<td>long applyAsLong(long operand)</td>
<td>接收一个 long 值，返回一个 long 结果</td>
</tr>
<tr>
<td>BiFunction&lt;T,U,R&gt;</td>
<td>R apply(T t, U u)</td>
<td>接收一个 T 类型和一个 U 类型对象，返回一个 R 类型对象结果</td>
</tr>
<tr>
<td><code>BinaryOperator&lt;T&gt;</code></td>
<td>T apply(T t, T u)</td>
<td>接收两个 T 类型对象，返回一个 T 类型对象结果</td>
</tr>
<tr>
<td>ToDoubleBiFunction&lt;T,U&gt;</td>
<td>double applyAsDouble(T t, U u)</td>
<td>接收一个 T 类型和一个 U 类型对象，返回一个 double</td>
</tr>
<tr>
<td>ToIntBiFunction&lt;T,U&gt;</td>
<td>int applyAsInt(T t, U u)</td>
<td>接收一个 T 类型和一个 U 类型对象，返回一个 int</td>
</tr>
<tr>
<td>ToLongBiFunction&lt;T,U&gt;</td>
<td>long applyAsLong(T t, U u)</td>
<td>接收一个 T 类型和一个 U 类型对象，返回一个 long</td>
</tr>
<tr>
<td>DoubleBinaryOperator</td>
<td>double applyAsDouble(double left, double right)</td>
<td>接收两个 double 值，返回一个 double 结果</td>
</tr>
<tr>
<td>IntBinaryOperator</td>
<td>int applyAsInt(int left, int right)</td>
<td>接收两个 int 值，返回一个 int 结果</td>
</tr>
<tr>
<td>LongBinaryOperator</td>
<td>long applyAsLong(long left, long right)</td>
<td>接收两个 long 值，返回一个 long 结果</td>
</tr>
</tbody></table>
<h4 id="2-3-Lambda-表达式语法"><a href="#2-3-Lambda-表达式语法" class="headerlink" title="2.3 Lambda 表达式语法"></a>2.3 Lambda 表达式语法</h4><p>Lambda 表达式是用来给【函数式接口】的变量或形参赋值用的。</p>
<p>其实本质上，Lambda 表达式是用于实现【函数式接口】的“抽象方法”</p>
<p>Lambda 表达式语法格式</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(形参列表) -&gt; &#123;Lambda 体&#125;</span><br></pre></td></tr></table></figure>

<p>说明：</p>
<ul>
<li>(形参列表) 它就是你要赋值的函数式接口的抽象方法的(形参列表)，照抄</li>
<li>{Lambda 体} 就是实现这个抽象方法的方法体</li>
<li><code>-&gt;</code> 称为 Lambda 操作符（减号和大于号中间不能有空格，而且必须是英文状态下半角输入方式）</li>
</ul>
<p>优化：Lambda 表达式可以精简</p>
<ul>
<li>当 {Lambda 体} 中只有一句语句时，可以省略 {} 和{;}</li>
<li>当 {Lambda 体} 中只有一句语句时，并且这个语句还是一个 return 语句，那么 return 也可以省略，但是如果 {;} 没有省略的话，return 是不能省略的</li>
<li>(形参列表)的类型可以省略</li>
<li>当 (形参列表) 的形参个数只有一个，那么可以把数据类型和 () 一起省略，但是形参名不能省略</li>
<li>当 (形参列表) 是空参时，() 不能省略</li>
</ul>
<p>示例代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestLambdaGrammer</span> </span>&#123;</span><br><span class="line">	<span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test1</span><span class="params">()</span></span>&#123;</span><br><span class="line">		<span class="comment">// 用 Lambda 表达式给 Runnable 接口的形参或变量赋值</span></span><br><span class="line">		<span class="comment">/*</span></span><br><span class="line"><span class="comment">		 * 确定两件事，才能写好 lambda 表达式</span></span><br><span class="line"><span class="comment">		 *（1）这个接口的抽象方法是否需要传入参数</span></span><br><span class="line"><span class="comment">		 *		public void run()</span></span><br><span class="line"><span class="comment">		 *（2）这个抽象方法的实现要干什么事</span></span><br><span class="line"><span class="comment">		 *		例如：我要打印“hello lambda&quot;</span></span><br><span class="line"><span class="comment">		 */</span></span><br><span class="line">		Runnable r = () -&gt; &#123;System.out.println(<span class="string">&quot;hello lambda&quot;</span>);&#125;;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test2</span><span class="params">()</span></span>&#123;</span><br><span class="line">		<span class="comment">// lambda 体省略了&#123;;&#125;</span></span><br><span class="line">		Runnable r = () -&gt; System.out.println(<span class="string">&quot;hello lambda&quot;</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test3</span><span class="params">()</span></span>&#123;</span><br><span class="line">		String[] arr = &#123;<span class="string">&quot;hello&quot;</span>，<span class="string">&quot;Hello&quot;</span>，<span class="string">&quot;java&quot;</span>，<span class="string">&quot;chai&quot;</span>&#125;;</span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 为 arr 数组排序，但是，想要不区分大小写</span></span><br><span class="line">		<span class="comment">/*</span></span><br><span class="line"><span class="comment">		 * public static &lt;T&gt; void sort(T[] a，Comparator&lt;? super T&gt; c)</span></span><br><span class="line"><span class="comment">		 * 这里要用 Lambda 表达式为 Comparator 类型的形参赋值</span></span><br><span class="line"><span class="comment">		 *</span></span><br><span class="line"><span class="comment">		 * 两件事：</span></span><br><span class="line"><span class="comment">		 *（1）这个接口的抽象方法：  int compare(T o1， T o2)</span></span><br><span class="line"><span class="comment">		 *（2）这个抽象方法要做什么事？</span></span><br><span class="line"><span class="comment">		 *		例如：这里要对 String 类型的元素，不区分大小写的比较大小</span></span><br><span class="line"><span class="comment">		 */</span></span><br><span class="line"><span class="comment">//		Arrays.sort(arr， (String o1， String o2) -&gt; &#123;return o1.compareToIgnoreCase(o2);&#125;);</span></span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 省略了&#123;return ;&#125;</span></span><br><span class="line"><span class="comment">//		Arrays.sort(arr， (String o1， String o2) -&gt;  o1.compareToIgnoreCase(o2));</span></span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 省略了两个 String</span></span><br><span class="line">		Arrays.sort(arr， (o1， o2) -&gt;  o1.compareToIgnoreCase(o2));</span><br><span class="line">		</span><br><span class="line">		<span class="keyword">for</span> (String string : arr) &#123;</span><br><span class="line">			System.out.println(string);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test4</span><span class="params">()</span></span>&#123;</span><br><span class="line">		ArrayList&lt;String&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">		list.add(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">		list.add(<span class="string">&quot;java&quot;</span>);</span><br><span class="line">		list.add(<span class="string">&quot;world&quot;</span>);</span><br><span class="line">		</span><br><span class="line">		<span class="comment">/*</span></span><br><span class="line"><span class="comment">		 * JDK1.8 给 Collection 系列的集合，准确的讲是在 Iterable 接口中，增加了一个默认方法</span></span><br><span class="line"><span class="comment">		 *		default void forEach(Consumer&lt;? super T&gt; action) </span></span><br><span class="line"><span class="comment">		 * 这个方法是用来遍历集合等的。代替原来的 foreach 循环的。</span></span><br><span class="line"><span class="comment">		 *</span></span><br><span class="line"><span class="comment">		 * 这个方法的形参是 Consumer 接口类型，它是函数式接口中消费型接口的代表</span></span><br><span class="line"><span class="comment">		 * 我现在调用这个方法，想要用 Lambda 表达式为 Consumer 接口类型形参赋值</span></span><br><span class="line"><span class="comment">		 *</span></span><br><span class="line"><span class="comment">		 * 两件事：</span></span><br><span class="line"><span class="comment">		 *（1）它的抽象方法：  void accept(T t)</span></span><br><span class="line"><span class="comment">		 *（2）抽象方法的实现要完成的事是什么</span></span><br><span class="line"><span class="comment">		 *		例如：这里要打印这个 t</span></span><br><span class="line"><span class="comment">		 */</span></span><br><span class="line"><span class="comment">//		list.forEach((String t) -&gt; &#123;System.out.println(t);&#125;);</span></span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 省略&#123;;&#125;</span></span><br><span class="line"><span class="comment">//		list.forEach((String t) -&gt; System.out.println(t));</span></span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 省略 String</span></span><br><span class="line"><span class="comment">//		list.forEach((t) -&gt; System.out.println(t));</span></span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 可以省略形参()</span></span><br><span class="line">		list.forEach(t -&gt; System.out.println(t));</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="2-4-Lambda-表达式练习"><a href="#2-4-Lambda-表达式练习" class="headerlink" title="2.4 Lambda 表达式练习"></a>2.4 Lambda 表达式练习</h4><h5 id="2-4-1-无参无返回值形式"><a href="#2-4-1-无参无返回值形式" class="headerlink" title="2.4.1 无参无返回值形式"></a>2.4.1 无参无返回值形式</h5><p>假如有自定义函数式接口 Call 如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Call</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">shout</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在测试类中声明一个如下方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">callSomething</span><span class="params">(Call call)</span></span>&#123;</span><br><span class="line">		call.shout();</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure>

<p>在测试类的 main 方法中调用 callSomething 方法，并用 Lambda 表达式为形参 call 赋值，可以喊出任意你想说的话。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestLambda</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">		callSomething(() -&gt; System.out.println(<span class="string">&quot;回家吃饭&quot;</span>));</span><br><span class="line">		callSomething(() -&gt; System.out.println(<span class="string">&quot;我爱你&quot;</span>));</span><br><span class="line">		callSomething(() -&gt; System.out.println(<span class="string">&quot;滚蛋&quot;</span>));</span><br><span class="line">		callSomething(() -&gt; System.out.println(<span class="string">&quot;回来&quot;</span>));</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">callSomething</span><span class="params">(Call call)</span></span>&#123;</span><br><span class="line">		call.shout();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Call</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">shout</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-2-消费型接口"><a href="#2-4-2-消费型接口" class="headerlink" title="2.4.2 消费型接口"></a>2.4.2 消费型接口</h5><p>代码示例：Consumer<T > 接口</p>
<p>在 JDK1.8 中 Collection 集合接口的父接口 Iterable 接口中增加了一个默认方法：</p>
<p><code>public default void forEach(Consumer&lt;? super T&gt; action) </code> 遍历 Collection 集合的每个元素，执行 “xxx 消费型” 操作。</p>
<p>在 JDK1.8 中 Map 集合接口中增加了一个默认方法：</p>
<p><code>public default void forEach(BiConsumer&lt;? super K，? super V&gt; action)</code> 遍历 Map 集合的每对映射关系，执行 “xxx 消费型” 操作。</p>
<p>案例：</p>
<p>（1）创建一个 Collection 系列的集合，添加你知道的编程语言，调用 forEach 方法遍历查看</p>
<p>（2）创建一个 Map 系列的集合，添加一些 (key，value) 键值对，例如，添加编程语言排名和语言名称，调用 forEach 方法遍历查看</p>
<p><img src= "/img/loading.gif" data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20211024222539.png" alt="1564370820279"></p>
<p>示例代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test1</span><span class="params">()</span></span>&#123;</span><br><span class="line">	List&lt;String&gt; list = Arrays.asList(<span class="string">&quot;java&quot;</span>，<span class="string">&quot;c&quot;</span>，<span class="string">&quot;python&quot;</span>，<span class="string">&quot;c++&quot;</span>，<span class="string">&quot;VB&quot;</span>，<span class="string">&quot;C#&quot;</span>);</span><br><span class="line">	list.forEach(s -&gt; System.out.println(s));</span><br><span class="line">   &#125;</span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test2</span><span class="params">()</span></span>&#123;</span><br><span class="line">	HashMap&lt;Integer，String&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">	map.put(<span class="number">1</span>， <span class="string">&quot;java&quot;</span>);</span><br><span class="line">	map.put(<span class="number">2</span>， <span class="string">&quot;c&quot;</span>);</span><br><span class="line">	map.put(<span class="number">3</span>， <span class="string">&quot;python&quot;</span>);</span><br><span class="line">	map.put(<span class="number">4</span>， <span class="string">&quot;c++&quot;</span>);</span><br><span class="line">      map.put(<span class="number">5</span>， <span class="string">&quot;VB&quot;</span>);</span><br><span class="line">      map.put(<span class="number">6</span>， <span class="string">&quot;C#&quot;</span>);</span><br><span class="line">	map.forEach((k，v) -&gt; System.out.println(k+<span class="string">&quot;-&gt;&quot;</span>+v));</span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-3-供给型接口"><a href="#2-4-3-供给型接口" class="headerlink" title="2.4.3 供给型接口"></a>2.4.3 供给型接口</h5><p>代码示例：Supplier<T > 接口</p>
<p>在 JDK1.8 中增加了 StreamAPI，java.util.stream.Stream<T > 是一个数据流。这个类型有一个静态方法：</p>
<p><code>public static &lt;T&gt; Stream&lt;T&gt; generate(Supplier&lt;T&gt; s)</code> 可以创建 Stream 的对象。而又包含一个 forEach 方法可以遍历流中的元素：<code>public void forEach(Consumer&lt;? super T&gt; action)</code>。</p>
<p>案例：</p>
<p>现在请调用 Stream 的 generate 方法，来产生一个流对象，并调用 Math.random()方法来产生数据，为 Supplier 函数式接口的形参赋值。最后调用 forEach 方法遍历流中的数据查看结果。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test2</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Stream.generate(() -&gt; Math.random()).forEach(num -&gt; System.out.println(num));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-4-功能型接口"><a href="#2-4-4-功能型接口" class="headerlink" title="2.4.4 功能型接口"></a>2.4.4 功能型接口</h5><p>代码示例：Funtion&lt;T，R&gt; 接口</p>
<p>在 JDK1.8 时 Map 接口增加了很多方法，例如：</p>
<p><code>public default void replaceAll(BiFunction&lt;? super K，? super V，? extends V&gt; function) </code> 按照 function 指定的操作替换 map 中的 value。</p>
<p><code>public default void forEach(BiConsumer&lt;? super K，? super V&gt; action)</code> 遍历 Map 集合的每对映射关系，执行 “xxx 消费型” 操作。</p>
<p>案例：</p>
<p>（1）声明一个 Employee 员工类型，包含编号、姓名、薪资。</p>
<p>（2）添加 n 个员工对象到一个 HashMap&lt;Integer，Employee &gt; 集合中，其中员工编号为 key，员工对象为 value.</p>
<p>（3）调用 Map 的 forEach 遍历集合</p>
<p>（4）调用 Map 的 replaceAll 方法，将其中薪资低于 10000 元的，薪资设置为 10000。</p>
<p>（5）再次调用 Map 的 forEach 遍历集合查看结果</p>
<p>Employee 类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Employee</span></span>&#123;</span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">int</span> id;</span><br><span class="line">	<span class="keyword">private</span> String name;</span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">double</span> salary;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Employee</span><span class="params">(<span class="keyword">int</span> id， String name， <span class="keyword">double</span> salary)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">super</span>();</span><br><span class="line">		<span class="keyword">this</span>.id = id;</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">		<span class="keyword">this</span>.salary = salary;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Employee</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">super</span>();</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getId</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> id;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setId</span><span class="params">(<span class="keyword">int</span> id)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.id = id;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">getSalary</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> salary;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSalary</span><span class="params">(<span class="keyword">double</span> salary)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.salary = salary;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="string">&quot;Employee [id=&quot;</span> + id + <span class="string">&quot;， name=&quot;</span> + name + <span class="string">&quot;， salary=&quot;</span> + salary + <span class="string">&quot;]&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>测试类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestLambda</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">		HashMap&lt;Integer，Employee&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">		Employee e1 = <span class="keyword">new</span> Employee(<span class="number">1</span>， <span class="string">&quot;张三&quot;</span>， <span class="number">8000</span>);</span><br><span class="line">		Employee e2 = <span class="keyword">new</span> Employee(<span class="number">2</span>， <span class="string">&quot;李四&quot;</span>， <span class="number">9000</span>);</span><br><span class="line">		Employee e3 = <span class="keyword">new</span> Employee(<span class="number">3</span>， <span class="string">&quot;王五&quot;</span>， <span class="number">10000</span>);</span><br><span class="line">		Employee e4 = <span class="keyword">new</span> Employee(<span class="number">4</span>， <span class="string">&quot;赵六&quot;</span>， <span class="number">11000</span>);</span><br><span class="line">		Employee e5 = <span class="keyword">new</span> Employee(<span class="number">5</span>， <span class="string">&quot;钱七&quot;</span>， <span class="number">12000</span>);</span><br><span class="line">		</span><br><span class="line">		map.put(e1.getId()， e1);</span><br><span class="line">		map.put(e2.getId()， e2);</span><br><span class="line">		map.put(e3.getId()， e3);</span><br><span class="line">		map.put(e4.getId()， e4);</span><br><span class="line">		map.put(e5.getId()， e5);</span><br><span class="line">		</span><br><span class="line">		map.forEach((k，v) -&gt; System.out.println(k+<span class="string">&quot;=&quot;</span>+v));</span><br><span class="line">		System.out.println();</span><br><span class="line">		</span><br><span class="line">		map.replaceAll((k，v)-&gt;&#123;</span><br><span class="line">			<span class="keyword">if</span>(v.getSalary()&lt;<span class="number">10000</span>)&#123;</span><br><span class="line">				v.setSalary(<span class="number">10000</span>);</span><br><span class="line">			&#125;</span><br><span class="line">			<span class="keyword">return</span> v;</span><br><span class="line">		&#125;);</span><br><span class="line">		map.forEach((k，v) -&gt; System.out.println(k+<span class="string">&quot;=&quot;</span>+v));</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-5-判断型接口"><a href="#2-4-5-判断型接口" class="headerlink" title="2.4.5 判断型接口"></a>2.4.5 判断型接口</h5><p>代码示例：Predicate<T > 接口</p>
<p>JDK1.8 时，Collecton<E > 接口增加了一下方法，其中一个如下：</p>
<p><code>public default boolean removeIf(Predicate&lt;? super E&gt; filter)</code> 用于删除集合中满足 filter 指定的条件判断的。</p>
<p><code>public default void forEach(Consumer&lt;? super T&gt; action) </code> 遍历 Collection 集合的每个元素，执行 “xxx 消费型” 操作。</p>
<p>案例：</p>
<p>（1）添加一些字符串到一个 Collection 集合中</p>
<p>（2）调用 forEach 遍历集合</p>
<p>（3）调用 removeIf 方法，删除其中字符串的长度 &lt; 5 的</p>
<p>（4）再次调用 forEach 遍历集合</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestLambda</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">		ArrayList&lt;String&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">		list.add(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">		list.add(<span class="string">&quot;java&quot;</span>);</span><br><span class="line">		list.add(<span class="string">&quot;atguigu&quot;</span>);</span><br><span class="line">		list.add(<span class="string">&quot;ok&quot;</span>);</span><br><span class="line">		list.add(<span class="string">&quot;yes&quot;</span>);</span><br><span class="line">		</span><br><span class="line">		list.forEach(str-&gt;System.out.println(str));</span><br><span class="line">		System.out.println();</span><br><span class="line">		</span><br><span class="line">		list.removeIf(str-&gt;str.length()&lt;<span class="number">5</span>);</span><br><span class="line">		list.forEach(str-&gt;System.out.println(str));</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-6-判断型接口"><a href="#2-4-6-判断型接口" class="headerlink" title="2.4.6 判断型接口"></a>2.4.6 判断型接口</h5><p>案例：</p>
<p>（1）声明一个 Employee 员工类型，包含编号、姓名、性别，年龄，薪资。</p>
<p>（2）声明一个 EmployeeSerice 员工管理类，包含一个 <code>ArrayList&lt;Employee&gt;</code> 集合的属性 all，在          EmployeeSerice 的构造器中，创建一些员工对象，为 all 集合初始化。</p>
<p>（3）在 EmployeeSerice 员工管理类中，声明一个方法：<code>ArrayList&lt;Employee&gt; get(Predicate&lt;Employee&gt; p)</code>，即将满足 p 指定的条件的员工，添加到一个新的 <code>ArrayList&lt;Employee&gt;</code> 集合中返回。</p>
<p>（4）在测试类中创建 EmployeeSerice 员工管理类的对象，并调用 get 方法，分别获取：</p>
<ul>
<li>所有员工对象</li>
<li>所有年龄超过 35 的员工</li>
<li>所有薪资高于 15000 的女员工</li>
<li>所有编号是偶数的员工</li>
<li>名字是 “张三” 的员工</li>
<li>年龄超过 25，薪资低于 10000 的男员工</li>
</ul>
<p>示例代码：</p>
<p>Employee 类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.pojo;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Employee</span></span>&#123;</span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">int</span> id;</span><br><span class="line">	<span class="keyword">private</span> String name;</span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">char</span> gender;</span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">double</span> salary;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Employee</span><span class="params">(<span class="keyword">int</span> id， String name， <span class="keyword">char</span> gender， <span class="keyword">int</span> age， <span class="keyword">double</span> salary)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">super</span>();</span><br><span class="line">		<span class="keyword">this</span>.id = id;</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">		<span class="keyword">this</span>.gender = gender;</span><br><span class="line">		<span class="keyword">this</span>.age = age;</span><br><span class="line">		<span class="keyword">this</span>.salary = salary;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">char</span> <span class="title">getGender</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> gender;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setGender</span><span class="params">(<span class="keyword">char</span> gender)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.gender = gender;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getAge</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> age;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setAge</span><span class="params">(<span class="keyword">int</span> age)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.age = age;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Employee</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">super</span>();</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getId</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> id;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setId</span><span class="params">(<span class="keyword">int</span> id)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.id = id;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">getSalary</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> salary;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSalary</span><span class="params">(<span class="keyword">double</span> salary)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.salary = salary;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="string">&quot;Employee [id=&quot;</span> + id + <span class="string">&quot;， name=&quot;</span> + name + <span class="string">&quot;， gender=&quot;</span> + gender + <span class="string">&quot;， age=&quot;</span> + age + <span class="string">&quot;， salary=&quot;</span> + salary</span><br><span class="line">				+ <span class="string">&quot;]&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>员工管理类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">EmployeeService</span></span>&#123;</span><br><span class="line">	<span class="keyword">private</span> ArrayList&lt;Employee&gt; all;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">EmployeeService</span><span class="params">()</span></span>&#123;</span><br><span class="line">		all = <span class="keyword">new</span> ArrayList&lt;Employee&gt;();</span><br><span class="line">		all.add(<span class="keyword">new</span> Employee(<span class="number">1</span>， <span class="string">&quot;张三&quot;</span>， <span class="string">&#x27;男&#x27;</span>， <span class="number">33</span>， <span class="number">8000</span>));</span><br><span class="line">		all.add(<span class="keyword">new</span> Employee(<span class="number">2</span>， <span class="string">&quot;翠花&quot;</span>， <span class="string">&#x27;女&#x27;</span>， <span class="number">23</span>， <span class="number">18000</span>));</span><br><span class="line">		all.add(<span class="keyword">new</span> Employee(<span class="number">3</span>， <span class="string">&quot;无能&quot;</span>， <span class="string">&#x27;男&#x27;</span>， <span class="number">46</span>， <span class="number">8000</span>));</span><br><span class="line">		all.add(<span class="keyword">new</span> Employee(<span class="number">4</span>， <span class="string">&quot;李四&quot;</span>， <span class="string">&#x27;女&#x27;</span>， <span class="number">23</span>， <span class="number">9000</span>));</span><br><span class="line">		all.add(<span class="keyword">new</span> Employee(<span class="number">5</span>， <span class="string">&quot;老王&quot;</span>， <span class="string">&#x27;男&#x27;</span>， <span class="number">23</span>， <span class="number">15000</span>));</span><br><span class="line">		all.add(<span class="keyword">new</span> Employee(<span class="number">6</span>， <span class="string">&quot;大嘴&quot;</span>， <span class="string">&#x27;男&#x27;</span>， <span class="number">23</span>， <span class="number">11000</span>));</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> ArrayList&lt;Employee&gt; <span class="title">get</span><span class="params">(Predicate&lt;Employee&gt; p)</span></span>&#123;</span><br><span class="line">		ArrayList&lt;Employee&gt; result = <span class="keyword">new</span> ArrayList&lt;Employee&gt;();</span><br><span class="line">		<span class="keyword">for</span> (Employee emp : all) &#123;</span><br><span class="line">			<span class="keyword">if</span>(p.test(emp))&#123;</span><br><span class="line">				result.add(emp);</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">return</span> result;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>测试类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestLambda</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">		EmployeeService es = <span class="keyword">new</span> EmployeeService();</span><br><span class="line">		</span><br><span class="line">		es.get(e -&gt; <span class="keyword">true</span>).forEach(e -&gt; System.out.println(e));</span><br><span class="line">		System.out.println();</span><br><span class="line">		es.get(e -&gt; e.getAge() &gt; <span class="number">35</span>).forEach(e-&gt;System.out.println(e));</span><br><span class="line">		System.out.println();</span><br><span class="line">		es.get(e -&gt; e.getSalary() &gt; <span class="number">15000</span> &amp;&amp; e.getGender() == <span class="string">&#x27;女&#x27;</span>).forEach(e-&gt;System.out.println(e));</span><br><span class="line">		System.out.println();</span><br><span class="line">		es.get(e -&gt; e.getId( )% <span class="number">2</span> == <span class="number">0</span>).forEach(e-&gt;System.out.println(e));</span><br><span class="line">		System.out.println();</span><br><span class="line">		es.get(e -&gt; <span class="string">&quot;张三&quot;</span>.equals(e.getName())).forEach(e -&gt; System.out.println(e));</span><br><span class="line">		System.out.println();</span><br><span class="line">		es.get(e -&gt; e.getAge() &gt; <span class="number">25</span> &amp;&amp; e.getSalary()&lt;<span class="number">10000</span> &amp;&amp; e.getGender()==<span class="string">&#x27;男&#x27;</span>).forEach(e-&gt;System.out.println(e));</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="2-5-方法引用与构造器引用"><a href="#2-5-方法引用与构造器引用" class="headerlink" title="2.5 方法引用与构造器引用"></a>2.5 方法引用与构造器引用</h4><p>Lambda 表达式是可以简化函数式接口的变量与形参赋值的语法。而方法引用和构造器引用是为了简化 Lambda 表达式的。当 Lambda 表达式满足一些特殊的情况时，还可以再简化：</p>
<p>（1）<strong>Lambda 体只有一句语句，并且是通过调用一个对象的 / 类现有的方法来完成的</strong></p>
<p>例如：System.out 对象，调用 println()方法来完成 Lambda 体</p>
<p>​          Math 类，调用 random()静态方法来完成 Lambda 体</p>
<p>（2）<strong>Method References</strong></p>
<p>例如：t-&gt;System.out.println(t)</p>
<p>​        () -&gt; Math.random() 都是无参</p>
<h5 id="2-5-1-方法引用"><a href="#2-5-1-方法引用" class="headerlink" title="2.5.1 方法引用"></a>2.5.1 方法引用</h5><p>方法引用的语法格式：</p>
<p>（1）实例对象名:: 实例方法        </p>
<p>（2）类名:: 静态方法</p>
<p>（3）类名:: 实例方法</p>
<p>说明：</p>
<ul>
<li>:: 称为方法引用操作符（两个: 中间不能有空格，而且必须英文状态下半角输入）</li>
<li>Lambda 表达式的形参列表，全部在 Lambda 体中使用上了，要么是作为调用方法的对象，要么是作为方法的实参。</li>
<li>在整个 Lambda 体中没有额外的数据。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">	<span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test4</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="comment">//		Runnable r = () -&gt; System.out.println(&quot;hello lambda&quot;);</span></span><br><span class="line">		Runnable r = System.out::println;<span class="comment">// 打印空行</span></span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 不能简化方法引用，因为 &quot;hello lambda&quot; 这个无法省略</span></span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test3</span><span class="params">()</span></span>&#123;</span><br><span class="line">		String[] arr = &#123;<span class="string">&quot;Hello&quot;</span>，<span class="string">&quot;java&quot;</span>，<span class="string">&quot;chai&quot;</span>&#125;;</span><br><span class="line"><span class="comment">//		Arrays.sort(arr， (s1，s2) -&gt; s1.compareToIgnoreCase(s2));</span></span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 用方法引用简化</span></span><br><span class="line">		<span class="comment">/*</span></span><br><span class="line"><span class="comment">		 * Lambda 表达式的形参，第一个（例如：s1），正好是调用方法的对象，</span></span><br><span class="line"><span class="comment">		 * 剩下的形参 (例如: s2) 正好是给这个方法的实参</span></span><br><span class="line"><span class="comment">		 */</span></span><br><span class="line">		Arrays.sort(arr， String::compareToIgnoreCase);</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test2</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="comment">//		Stream&lt;Double&gt; stream = Stream.generate(() -&gt; Math.random());</span></span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 用方法引用简化</span></span><br><span class="line">		Stream&lt;Double&gt; stream = Stream.generate(Math::random);</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test1</span><span class="params">()</span></span>&#123;</span><br><span class="line">		List&lt;Integer&gt; list = Arrays.asList(<span class="number">1</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">8</span>，<span class="number">9</span>);</span><br><span class="line">		</span><br><span class="line">		<span class="comment">// list.forEach(t -&gt; System.out.println(t));</span></span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 用方法再简化</span></span><br><span class="line">		list.forEach(System.out::println);</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-5-2-构造器引用"><a href="#2-5-2-构造器引用" class="headerlink" title="2.5.2 构造器引用"></a>2.5.2 构造器引用</h5><p>（1）当 Lambda 表达式是创建一个对象，并且满足 Lambda 表达式形参，正好是给创建这个对象的构造器的实参列表。</p>
<p>（2) 当 Lambda 表达式是创建一个数组对象，并满足 Lambda 表达式形参，正好是给创建这个数组对象的长度</p>
<p>构造器引用的语法格式：</p>
<ul>
<li>类名::new</li>
<li>数组类型名::new</li>
</ul>
<p>示例代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestMethodReference</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">teset04</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		Stream&lt;Integer&gt; stream = Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>);</span><br><span class="line">		Stream&lt;<span class="keyword">int</span>[]&gt; stream2 = stream.map(<span class="keyword">int</span>[]::<span class="keyword">new</span>);</span><br><span class="line">	&#125;    </span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">teset02</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		Stream&lt;String&gt; stream = Stream.of(<span class="string">&quot;1.0&quot;</span>，<span class="string">&quot;2.3&quot;</span>，<span class="string">&quot;4.4&quot;</span>);</span><br><span class="line">		</span><br><span class="line"><span class="comment">//		Stream&lt;BigDecimal&gt; stream2 = stream.map(num -&gt; new BigDecimal(num));</span></span><br><span class="line">		</span><br><span class="line">		Stream&lt;BigDecimal&gt; stream2 = stream.map(BigDecimal::<span class="keyword">new</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test1</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="comment">//		Supplier&lt;String&gt; s = () -&gt; new String();// 通过供给型接口，提供一个空字符串对象</span></span><br><span class="line">		</span><br><span class="line">		<span class="comment">// 构造器引用</span></span><br><span class="line">		Supplier&lt;String&gt; s = String::<span class="keyword">new</span>;<span class="comment">// 通过供给型接口，提供一个空字符串对象</span></span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="第三章-Stream-流"><a href="#第三章-Stream-流" class="headerlink" title="第三章 Stream 流"></a>第三章 Stream 流</h2><h3 id="1-学习目标-2"><a href="#1-学习目标-2" class="headerlink" title="1. 学习目标"></a>1. 学习目标</h3><ul>
<li><p>能够理解流与集合相比的优点</p>
</li>
<li><p>能够理解流的延迟执行特点</p>
</li>
<li><p>能够通过集合、映射或数组获取流</p>
</li>
<li><p>能够掌握常用的流操作</p>
</li>
</ul>
<h3 id="2-内容讲解-2"><a href="#2-内容讲解-2" class="headerlink" title="2. 内容讲解"></a>2. 内容讲解</h3><h4 id="2-1-Stream-流的优势"><a href="#2-1-Stream-流的优势" class="headerlink" title="2.1 Stream 流的优势"></a>2.1 Stream 流的优势</h4><p>Java8 中有两大最为重要的改变。第一个是 Lambda 表达式；另外一个则是 Stream API。</p>
<p>Stream API ( java.util.stream) 把真正的函数式编程风格引入到 Java 中。这是目前为止对 Java 类库最好的补充，因为 Stream API 可以极大提高 Java 程序员的生产力，让程序员写出高效率、干净、简洁的代码。</p>
<p>Stream 是 Java8 中<strong>处理集合</strong>的关键抽象概念，它可以指定你希望对集合进行的操作，可以执行非常复杂的查找、过滤和映射数据等操作。 使用 Stream API 对集合数据进行操作，就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简言之，Stream API 提供了一种高效且易于使用的处理数据的方式。</p>
<p>Stream 是数据渠道，用于操作数据源（集合、数组等）所生成的元素序列。“集合讲的是数据，负责存储数据，Stream 流讲的是计算，负责处理数据！”</p>
<p>注意：</p>
<p>①Stream 自己不会存储元素。</p>
<p>②Stream 不会改变源对象。每次处理都会返回一个持有结果的新 Stream。</p>
<p>③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。</p>
<h4 id="2-2-Stream-流的使用步骤"><a href="#2-2-Stream-流的使用步骤" class="headerlink" title="2.2 Stream 流的使用步骤"></a>2.2 Stream 流的使用步骤</h4><p>Stream 的操作三个步骤：</p>
<p>1- 创建 Stream：通过一个数据源（如：集合、数组），获取一个流</p>
<p>2- 中间操作：中间操作是个操作链，对数据源的数据进行 n 次处理，但是在终结操作前，并不会真正执行。</p>
<p>3- 终止操作：一旦执行终止操作，就执行中间操作链，最终产生结果并结束 Stream.</p>
<p><img src= "/img/loading.gif" data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20211024222556.png" alt="1560769396655"></p>
<h4 id="2-3-创建-Stream"><a href="#2-3-创建-Stream" class="headerlink" title="2.3 创建 Stream"></a>2.3 创建 Stream</h4><h5 id="2-3-1-创建-Stream-方式一：通过集合"><a href="#2-3-1-创建-Stream-方式一：通过集合" class="headerlink" title="2.3.1 创建 Stream 方式一：通过集合"></a>2.3.1 创建 Stream 方式一：通过集合</h5><p>Java8 中的 Collection 接口被扩展，提供了两个获取流的方法：</p>
<ul>
<li><code>public default Stream&lt;E&gt; stream()</code> : 返回一个顺序流</li>
<li><code>public default Stream&lt;E&gt; parallelStream()</code> : 返回一个并行流</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test01</span><span class="params">()</span></span>&#123;</span><br><span class="line">    List&lt;Integer&gt; list = Arrays.asList(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//JDK1.8 中，Collection 系列集合增加了方法</span></span><br><span class="line">    Stream&lt;Integer&gt; stream = list.stream();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-3-2-创建-Stream-方式二：通过数组"><a href="#2-3-2-创建-Stream-方式二：通过数组" class="headerlink" title="2.3.2 创建 Stream 方式二：通过数组"></a>2.3.2 创建 Stream 方式二：通过数组</h5><p>Java8 中的 Arrays 的静态方法 stream() 可以获取数组流：</p>
<ul>
<li><code>public static &lt;T&gt; Stream&lt;T&gt; stream(T[] array)</code>: 返回一个流</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test03</span><span class="params">()</span></span>&#123;</span><br><span class="line">    String[] arr = &#123;<span class="string">&quot;hello&quot;</span>，<span class="string">&quot;world&quot;</span>&#125;;</span><br><span class="line">    Stream&lt;String&gt; stream = Arrays.stream(arr);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test02</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span>[] arr = &#123;<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>&#125;;</span><br><span class="line">    IntStream stream = Arrays.stream(arr);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>重载形式，能够处理对应基本类型的数组：</p>
<ul>
<li>public static IntStream stream(int[] array)：返回一个整型数据流</li>
<li>public static LongStream stream(long[] array)：返回一个长整型数据流</li>
<li>public static DoubleStream stream(double[] array)：返回一个浮点型数据流</li>
</ul>
<h5 id="2-3-3-创建-Stream-方式三：通过-Stream-的-of"><a href="#2-3-3-创建-Stream-方式三：通过-Stream-的-of" class="headerlink" title="2.3.3 创建 Stream 方式三：通过 Stream 的 of()"></a>2.3.3 创建 Stream 方式三：通过 Stream 的 of()</h5><p>可以调用 Stream 类静态方法 of()， 通过显示值创建一个流。它可以接收任意数量的参数。</p>
<ul>
<li>public static<T> Stream<T> of(T… values) : 返回一个顺序流</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test04</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Stream&lt;Integer&gt; stream = Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>);</span><br><span class="line">    stream.forEach(System.out::println);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-2-4-创建-Stream-方式四：创建无限流"><a href="#2-2-4-创建-Stream-方式四：创建无限流" class="headerlink" title="2.2.4 创建 Stream 方式四：创建无限流"></a>2.2.4 创建 Stream 方式四：创建无限流</h5><p>可以使用静态方法 Stream.iterate() 和 Stream.generate()， 创建无限流。</p>
<ul>
<li>public static<T> Stream<T> iterate(final T seed， final UnaryOperator<T> f): 返回一个无限流</li>
<li>public static<T> Stream<T> generate(Supplier<T> s) ：返回一个无限流</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test06</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">		 *Stream&lt;T&gt; iterate(T seed， UnaryOperator&lt;T&gt; f)  </span></span><br><span class="line"><span class="comment">		 *UnaryOperator 接口，SAM 接口，抽象方法：</span></span><br><span class="line"><span class="comment">		 *</span></span><br><span class="line"><span class="comment">		 *UnaryOperator&lt;T&gt; extends Function&lt;T，T&gt;</span></span><br><span class="line"><span class="comment">		 *		T apply(T t)</span></span><br><span class="line"><span class="comment">		 */</span></span><br><span class="line">    Stream&lt;Integer&gt; stream = Stream.iterate(<span class="number">1</span>， num -&gt; num+=<span class="number">2</span>);</span><br><span class="line">    <span class="comment">//		stream = stream.limit(10);</span></span><br><span class="line">    stream.forEach(System.out::println);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test05</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Stream&lt;Double&gt; stream = Stream.generate(Math::random);</span><br><span class="line">    stream.forEach(System.out::println);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="2-4-中间操作"><a href="#2-4-中间操作" class="headerlink" title="2.4  中间操作"></a>2.4  中间操作</h4><p>多个中间操作可以连接起来形成一个流水线，除非流水线上触发终止操作，否则中间操作不会执行任何的处理！而在终止操作时一次性全部处理，称为“惰性求值”。</p>
<h5 id="2-4-1-filer-过滤"><a href="#2-4-1-filer-过滤" class="headerlink" title="2.4.1 filer 过滤"></a>2.4.1 filer 过滤</h5><p><code>filter(Predicate p)</code> 可以接收 Lambda ， 从流中排除某些元素</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test01</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="comment">// 1、创建 Stream</span></span><br><span class="line">    Stream&lt;Integer&gt; stream = Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">6</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2、加工处理</span></span><br><span class="line">    <span class="comment">// 过滤：filter(Predicate p)</span></span><br><span class="line">    <span class="comment">// 把里面的偶数拿出来</span></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">		 *filter(Predicate p)</span></span><br><span class="line"><span class="comment">		 *Predicate 是函数式接口，抽象方法：boolean test(T t)</span></span><br><span class="line"><span class="comment">		 */</span></span><br><span class="line">    stream = stream.filter(t -&gt; t%<span class="number">2</span>==<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//3、终结操作：例如：遍历</span></span><br><span class="line">    stream.forEach(System.out::println);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-2-distinct-去重"><a href="#2-4-2-distinct-去重" class="headerlink" title="2.4.2 distinct 去重"></a>2.4.2 distinct 去重</h5><p><code>distinct()</code> 通过流所生成元素的 equals() 去除重复元素</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test02</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">6</span>，<span class="number">2</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">4</span>，<span class="number">5</span>)</span><br><span class="line">        .distinct()</span><br><span class="line">        .forEach(System.out::println);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-3-limit-截断"><a href="#2-4-3-limit-截断" class="headerlink" title="2.4.3 limit 截断"></a>2.4.3 limit 截断</h5><p><code>limit(long maxSize)</code> 截断流，使其元素不超过给定数量</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test03</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">6</span>，<span class="number">2</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">4</span>，<span class="number">5</span>)</span><br><span class="line">        .limit(<span class="number">3</span>)</span><br><span class="line">        .forEach(System.out::println);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test04</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">6</span>，<span class="number">7</span>)</span><br><span class="line">        .distinct()  <span class="comment">//(1，2，3，4，5，6，7)</span></span><br><span class="line">        .filter(t -&gt; t%<span class="number">2</span>!=<span class="number">0</span>) <span class="comment">//(1，3，5，7)</span></span><br><span class="line">        .limit(<span class="number">3</span>)</span><br><span class="line">        .forEach(System.out::println);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-4-skip-跳过"><a href="#2-4-4-skip-跳过" class="headerlink" title="2.4.4 skip 跳过"></a>2.4.4 skip 跳过</h5><p><code>skip(long n)</code> 跳过元素，返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个，则返回一个空流。与 limit(n) 互补</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test05</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">6</span>，<span class="number">2</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">4</span>，<span class="number">5</span>)</span><br><span class="line">        .skip(<span class="number">5</span>)</span><br><span class="line">        .forEach(System.out::println);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-5-peek-对每个元素进行-Lambda-操作"><a href="#2-4-5-peek-对每个元素进行-Lambda-操作" class="headerlink" title="2.4.5 peek 对每个元素进行 Lambda 操作"></a>2.4.5 peek 对每个元素进行 Lambda 操作</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test06</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">long</span> count = Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">6</span>，<span class="number">2</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">4</span>，<span class="number">5</span>)</span><br><span class="line">        .distinct()</span><br><span class="line">        <span class="comment">// Consumer 消费接口的抽象方法  void accept(T t)，无返回值，不改变源数据</span></span><br><span class="line">        .peek(System.out::println) </span><br><span class="line"></span><br><span class="line">        .count();</span><br><span class="line">    System.out.println(<span class="string">&quot;count=&quot;</span>+count);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h5 id="2-4-6-sorted-排序"><a href="#2-4-6-sorted-排序" class="headerlink" title="2.4.6 sorted 排序"></a>2.4.6 sorted 排序</h5><p><code>sorted()</code> 产生一个新流，其中按自然顺序排序</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test07</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Stream.of(<span class="number">11</span>，<span class="number">2</span>，<span class="number">39</span>，<span class="number">4</span>，<span class="number">54</span>，<span class="number">6</span>，<span class="number">2</span>，<span class="number">22</span>，<span class="number">3</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">54</span>，<span class="number">54</span>)</span><br><span class="line">        .distinct()</span><br><span class="line">        .sorted()</span><br><span class="line">        .limit(<span class="number">3</span>)</span><br><span class="line">        .forEach(System.out::println);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>sorted(Comparator com)</code> 产生一个新流，其中按比较器顺序排序</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test08</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="comment">// 希望能够找出前三个最大值，前三名最大的，不重复</span></span><br><span class="line">    Stream.of(<span class="number">11</span>，<span class="number">2</span>，<span class="number">39</span>，<span class="number">4</span>，<span class="number">54</span>，<span class="number">6</span>，<span class="number">2</span>，<span class="number">22</span>，<span class="number">3</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">54</span>，<span class="number">54</span>)</span><br><span class="line">        .distinct()</span><br><span class="line">        .sorted((n1，n2) -&gt; n2 - n1)</span><br><span class="line">        .limit(<span class="number">3</span>)</span><br><span class="line">        .forEach(System.out::println);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-7-map-映射成新元素"><a href="#2-4-7-map-映射成新元素" class="headerlink" title="2.4.7 map 映射成新元素"></a>2.4.7 map 映射成新元素</h5><p><code>map(Function f)</code> 接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test09</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>)</span><br><span class="line">        .map(t -&gt; t+=<span class="number">1</span>)<span class="comment">// Function&lt;T，R &gt; 接口抽象方法 R apply(T t)</span></span><br><span class="line">        .forEach(System.out::println);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test10</span><span class="params">()</span></span>&#123;</span><br><span class="line">    String[] arr = &#123;<span class="string">&quot;hello&quot;</span>，<span class="string">&quot;world&quot;</span>，<span class="string">&quot;java&quot;</span>&#125;;</span><br><span class="line"></span><br><span class="line">    Arrays.stream(arr)</span><br><span class="line">        .map(t -&gt; t.toUpperCase())</span><br><span class="line">        .forEach(System.out::println);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-4-9-所有中间操作方法列表"><a href="#2-4-9-所有中间操作方法列表" class="headerlink" title="2.4.9 所有中间操作方法列表"></a>2.4.9 所有中间操作方法列表</h5><table>
<thead>
<tr>
<th>**方  法 **</th>
<th>**描  述 **</th>
</tr>
</thead>
<tbody><tr>
<td><strong>filter(Predicate p)</strong></td>
<td>接收 Lambda ， 从流中排除某些元素</td>
</tr>
<tr>
<td><strong>distinct()</strong></td>
<td>筛选，通过流所生成元素的 equals() 去除重复元素</td>
</tr>
<tr>
<td><strong>limit(long maxSize)</strong></td>
<td>截断流，使其元素不超过给定数量</td>
</tr>
<tr>
<td><strong>skip(long n)</strong></td>
<td>跳过元素，返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个，则返回一个空流。与 limit(n) 互补</td>
</tr>
<tr>
<td><strong>peek(Consumer</strong> <strong>action)</strong></td>
<td>接收 Lambda，对流中的每个数据执行 Lambda 体操作</td>
</tr>
<tr>
<td><strong>sorted()</strong></td>
<td>产生一个新流，其中按自然顺序排序</td>
</tr>
<tr>
<td><strong>sorted(Comparator com)</strong></td>
<td>产生一个新流，其中按比较器顺序排序</td>
</tr>
<tr>
<td><strong>map(Function f)</strong></td>
<td>接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素。</td>
</tr>
<tr>
<td><strong>mapToDouble(ToDoubleFunction f)</strong></td>
<td>接收一个函数作为参数，该函数会被应用到每个元素上，产生一个新的 DoubleStream。</td>
</tr>
<tr>
<td><strong>mapToInt(ToIntFunction f)</strong></td>
<td>接收一个函数作为参数，该函数会被应用到每个元素上，产生一个新的 IntStream。</td>
</tr>
<tr>
<td><strong>mapToLong(ToLongFunction f)</strong></td>
<td>接收一个函数作为参数，该函数会被应用到每个元素上，产生一个新的 LongStream。</td>
</tr>
<tr>
<td><strong>flatMap(Function f)</strong></td>
<td>接收一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连接成一个流</td>
</tr>
</tbody></table>
<h4 id="2-5-终结操作"><a href="#2-5-终结操作" class="headerlink" title="2.5  终结操作"></a>2.5  终结操作</h4><p>终端操作会从流的流水线生成结果。其结果可以是任何不是流的值，例如：List、Integer，甚至是 void。流进行了终止操作后，不能再次使用。</p>
<h5 id="2-5-1-forEach-迭代"><a href="#2-5-1-forEach-迭代" class="headerlink" title="2.5.1 forEach 迭代"></a>2.5.1 forEach 迭代</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test01</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>)</span><br><span class="line">        .forEach(System.out::println);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-5-2-count-返回流中元素总数"><a href="#2-5-2-count-返回流中元素总数" class="headerlink" title="2.5.2 count 返回流中元素总数"></a>2.5.2 count 返回流中元素总数</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test02</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">long</span> count = Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">3</span>，<span class="number">4</span>，<span class="number">5</span>)</span><br><span class="line">        .count();</span><br><span class="line">    System.out.println(<span class="string">&quot;count =&quot;</span> + count); <span class="comment">// 5</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-5-3-allMatch-检查是否匹配所有元素"><a href="#2-5-3-allMatch-检查是否匹配所有元素" class="headerlink" title="2.5.3 allMatch 检查是否匹配所有元素"></a>2.5.3 allMatch 检查是否匹配所有元素</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test03</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">boolean</span> result = Stream.of(<span class="number">1</span>，<span class="number">3</span>，<span class="number">5</span>，<span class="number">7</span>，<span class="number">9</span>)</span><br><span class="line">        .allMatch(t -&gt; t%<span class="number">2</span>!=<span class="number">0</span>);</span><br><span class="line">    System.out.println(result);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-5-4-anyMatch-检查是否至少匹配一个元素"><a href="#2-5-4-anyMatch-检查是否至少匹配一个元素" class="headerlink" title="2.5.4 anyMatch 检查是否至少匹配一个元素"></a>2.5.4 anyMatch 检查是否至少匹配一个元素</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test04</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">boolean</span> result = Stream.of(<span class="number">1</span>，<span class="number">3</span>，<span class="number">5</span>，<span class="number">7</span>，<span class="number">9</span>)</span><br><span class="line">        .anyMatch(t -&gt; t%<span class="number">2</span>==<span class="number">0</span>);</span><br><span class="line">    System.out.println(result);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-5-5-findFirst-返回第一个元素"><a href="#2-5-5-findFirst-返回第一个元素" class="headerlink" title="2.5.5 findFirst 返回第一个元素"></a>2.5.5 findFirst 返回第一个元素</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test08</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Optional&lt;Integer&gt; opt = Stream.of(<span class="number">1</span>，<span class="number">3</span>，<span class="number">5</span>，<span class="number">7</span>，<span class="number">9</span>).findFirst();</span><br><span class="line">    System.out.println(opt.get());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-5-6-max-返回流中最大值"><a href="#2-5-6-max-返回流中最大值" class="headerlink" title="2.5.6 max 返回流中最大值"></a>2.5.6 max 返回流中最大值</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test02</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Optional&lt;Integer&gt; max = Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">7</span>，<span class="number">8</span>)</span><br><span class="line">        .max(Integer::compareTo); <span class="comment">// 不能用 Math.Max 因为集合存储的是对象</span></span><br><span class="line">    System.out.println(max.get());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-5-7-reduce-可以将流中元素反复结合操作起来，得到一个值"><a href="#2-5-7-reduce-可以将流中元素反复结合操作起来，得到一个值" class="headerlink" title="2.5.7 reduce 可以将流中元素反复结合操作起来，得到一个值"></a>2.5.7 reduce 可以将流中元素反复结合操作起来，得到一个值</h5><p><code>T reduce(T iden， BinaryOperator b)</code> 可以将流中元素反复结合起来，得到一个值。返回 T</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test03</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Integer reduce = Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">7</span>，<span class="number">8</span>)</span><br><span class="line">        .reduce(<span class="number">0</span>， (t1，t2) -&gt; t1+t2);<span class="comment">// BinaryOperator 接口   T apply(T t1， T t2)</span></span><br><span class="line">    System.out.println(reduce);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>U reduce(BinaryOperator b)</code> 可以将流中元素反复结合起来，得到一个值。返回 Optional<T></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test04</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Optional&lt;Integer&gt; max = Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">7</span>，<span class="number">8</span>)</span><br><span class="line">        .reduce((t1，t2) -&gt; t1 &gt; t2 ? t1:t2);<span class="comment">//BinaryOperator 接口   T apply(T t1， T t2)</span></span><br><span class="line">    System.out.println(max.get());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-5-8-collect-将流转换为其他形式-很重要"><a href="#2-5-8-collect-将流转换为其他形式-很重要" class="headerlink" title="2.5.8 collect 将流转换为其他形式(很重要)"></a>2.5.8 collect 将流转换为其他形式(很重要)</h5><p><code>R collect(Collector c)</code> 将流转换为其他形式。接收一个 Collector 接口的实现，用于给 Stream 中元素做汇总的方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test14</span><span class="params">()</span></span>&#123;</span><br><span class="line">    List&lt;Integer&gt; list = Stream.of(<span class="number">1</span>，<span class="number">2</span>，<span class="number">4</span>，<span class="number">5</span>，<span class="number">7</span>，<span class="number">8</span>)</span><br><span class="line">        .filter(t -&gt; t%<span class="number">2</span> == <span class="number">0</span>)</span><br><span class="line">        .collect(Collectors.toList());</span><br><span class="line"></span><br><span class="line">    System.out.println(list);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-5-9-所有终结操作的方法列表"><a href="#2-5-9-所有终结操作的方法列表" class="headerlink" title="2.5.9 所有终结操作的方法列表"></a>2.5.9 所有终结操作的方法列表</h5><table>
<thead>
<tr>
<th>**方法 **</th>
<th>**描述 **</th>
</tr>
</thead>
<tbody><tr>
<td>**boolean ** <strong>allMatch(Predicate p)</strong></td>
<td>检查是否匹配所有元素</td>
</tr>
<tr>
<td><strong>boolean</strong> <strong>anyMatch</strong>(<strong>Predicate p</strong>)</td>
<td>检查是否至少匹配一个元素</td>
</tr>
<tr>
<td><strong>boolean</strong> <strong>noneMatch(Predicate  p)</strong></td>
<td>检查是否没有匹配所有元素</td>
</tr>
<tr>
<td><strong>Optional<T></strong> <strong>findFirst()</strong></td>
<td>返回第一个元素</td>
</tr>
<tr>
<td><strong>Optional<T></strong> <strong>findAny()</strong></td>
<td>返回当前流中的任意元素</td>
</tr>
<tr>
<td><strong>long</strong> <strong>count()</strong></td>
<td>返回流中元素总数</td>
</tr>
<tr>
<td><strong>Optional<T></strong> <strong>max(Comparator c)</strong></td>
<td>返回流中最大值，max 已写好判断逻辑代码，直接调用即可</td>
</tr>
<tr>
<td><strong>Optional<T></strong> <strong>min(Comparator c)</strong></td>
<td>返回流中最小值</td>
</tr>
<tr>
<td><strong>void</strong> <strong>forEach(Consumer c)</strong></td>
<td>迭代</td>
</tr>
<tr>
<td><strong>T</strong> <strong>reduce(T iden, BinaryOperator b)</strong></td>
<td>可以将流中元素反复结合起来，得到一个值。返回 T</td>
</tr>
<tr>
<td><strong>U</strong> <strong>reduce(BinaryOperator b)</strong></td>
<td>可以将流中元素反复结合起来，得到一个值。返回 Optional<T></td>
</tr>
<tr>
<td><strong>R</strong> <strong>collect(Collector c)</strong></td>
<td>将流转换为其他形式。接收一个 Collector 接口的实现，用于给 Stream 中元素做汇总的方法</td>
</tr>
</tbody></table>
<p>Collector 接口中方法的实现决定了如何对流执行收集的操作(如收集到 List、Set、Map)。另外， Collectors 实用类提供了很多静态方法，可以方便地创建常见收集器实例。</p>
<h4 id="2-6-练习"><a href="#2-6-练习" class="headerlink" title="2.6 练习"></a>2.6 练习</h4><p>案例：</p>
<p>现在有两个 ArrayList 集合存储队伍当中的多个成员姓名，要求使用传统的 for 循环（或增强 for 循环）依次进行以下若干操作步骤：</p>
<ol>
<li>第一个队伍只要名字为 3 个字的成员姓名；存储到一个新集合中。</li>
<li>第一个队伍筛选之后只要前 3 个人；存储到一个新集合中。</li>
<li>第二个队伍只要姓张的成员姓名；存储到一个新集合中。</li>
<li>第二个队伍筛选之后不要前 2 个人；存储到一个新集合中。</li>
<li>将两个队伍合并为一个队伍；存储到一个新集合中。</li>
<li>根据姓名创建 Person 对象；存储到一个新集合中。</li>
<li>打印整个队伍的 Person 对象信息。</li>
</ol>
<p>Person 类的代码为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.atguigu.stream;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Person</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Person</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;Person&#123;&quot;</span> +</span><br><span class="line">                <span class="string">&quot;name=&#x27;&quot;</span> + name + <span class="string">&#x27;\&#x27;&#x27;</span> +</span><br><span class="line">                <span class="string">&#x27;&#125;&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>两个队伍（集合）的代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">      <span class="comment">// 第一支队伍</span></span><br><span class="line">      List&lt;String&gt; one = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        one.add(<span class="string">&quot;迪丽热巴&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;宋远桥&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;苏星河&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;石破天&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;石中玉&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;老子&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;庄子&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;洪七公&quot;</span>);</span><br><span class="line"></span><br><span class="line">        List&lt;String&gt; two = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        two.add(<span class="string">&quot;古力娜扎&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;张无忌&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;赵丽颖&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;张三丰&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;尼古拉斯赵四&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;张天爱&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;张二狗&quot;</span>);</span><br><span class="line">    </span><br><span class="line">		<span class="comment">// .... 编写代码完成题目要求 </span></span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>参考答案：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">       <span class="comment">// 第一支队伍</span></span><br><span class="line">        ArrayList&lt;String&gt; one = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        one.add(<span class="string">&quot;迪丽热巴&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;宋远桥&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;苏星河&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;石破天&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;石中玉&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;老子&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;庄子&quot;</span>);</span><br><span class="line">        one.add(<span class="string">&quot;洪七公&quot;</span>);</span><br><span class="line">    </span><br><span class="line">        <span class="comment">// 第二支队伍</span></span><br><span class="line">        ArrayList&lt;String&gt; two = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        two.add(<span class="string">&quot;古力娜扎&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;张无忌&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;赵丽颖&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;张三丰&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;尼古拉斯赵四&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;张天爱&quot;</span>);</span><br><span class="line">        two.add(<span class="string">&quot;张二狗&quot;</span>);</span><br><span class="line">        </span><br><span class="line">		<span class="comment">// 第一个队伍只要名字为 3 个字的成员姓名；</span></span><br><span class="line">        <span class="comment">// 第一个队伍筛选之后只要前 3 个人；</span></span><br><span class="line">        Stream&lt;String&gt; streamOne = one.stream().filter(s ‐&gt; s.length() == <span class="number">3</span>).limit(<span class="number">3</span>);</span><br><span class="line">    </span><br><span class="line">        <span class="comment">// 第二个队伍只要姓张的成员姓名；</span></span><br><span class="line">        <span class="comment">// 第二个队伍筛选之后不要前 2 个人；</span></span><br><span class="line">        Stream&lt;String&gt; streamTwo = two.stream().filter(s ‐&gt; s.startsWith(<span class="string">&quot;张&quot;</span>)).skip(<span class="number">2</span>);</span><br><span class="line">    </span><br><span class="line">        <span class="comment">// 将两个队伍合并为一个队伍；</span></span><br><span class="line">        <span class="comment">// 根据姓名创建 Person 对象；</span></span><br><span class="line">        <span class="comment">// 打印整个队伍的 Person 对象信息。</span></span><br><span class="line">        Stream.concat(streamOne,streamTwo).map(Person::<span class="keyword">new</span>).forEach(System.out::println);        </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="第四章-Optional-类"><a href="#第四章-Optional-类" class="headerlink" title="第四章 Optional 类"></a>第四章 Optional 类</h2><p>到目前为止，臭名昭著的空指针异常是导致 Java 应用程序失败的最常见原因。以前，为了解决空指针异常，Google 公司著名的 Guava 项目引入了 Optional 类，Guava 通过使用检查空值的方式来防止代码污染，它鼓励程序员写更干净的代码。受到 Google Guava 的启发，Optional 类已经成为 Java 8 类库的一部分。</p>
<p>Optional 实际上是个容器：它可以保存类型 T 的值，或者仅仅保存 null。Optional 提供很多有用的方法，这样我们就不用显式进行空值检测。</p>
<h3 id="1-API"><a href="#1-API" class="headerlink" title="1 API"></a>1 API</h3><h4 id="1-1-创建-Optional-对象"><a href="#1-1-创建-Optional-对象" class="headerlink" title="1.1 创建 Optional 对象"></a>1.1 创建 Optional 对象</h4><p>（1）<code>static &lt;T&gt; Optional&lt;T&gt; empty()</code> ：用来创建一个空的 Optional</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test01</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Optional&lt;String&gt; opt = Optional.empty();</span><br><span class="line">    System.out.println(opt);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>（2）<code>static &lt;T&gt; Optional&lt;T&gt; of(T value)</code> ：用来创建一个非空的 Optional</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test02</span><span class="params">()</span></span>&#123;</span><br><span class="line">    String str = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">    Optional&lt;String&gt; opt = Optional.of(str);</span><br><span class="line">    System.out.println(opt);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>（3）<code>static &lt;T&gt; Optional&lt;T&gt; ofNullable(T value)</code> ：用来创建一个可能是空，也可能非空的 Optional</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test03</span><span class="params">()</span></span>&#123;</span><br><span class="line">    String str = <span class="keyword">null</span>;</span><br><span class="line">    Optional&lt;String&gt; opt = Optional.ofNullable(str);</span><br><span class="line">    System.out.println(opt);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="2-2-从-Optional-容器中取出所包装的对象"><a href="#2-2-从-Optional-容器中取出所包装的对象" class="headerlink" title="2.2 从 Optional 容器中取出所包装的对象"></a>2.2 从 Optional 容器中取出所包装的对象</h5><h5 id="（1）T-get-：要求-Optional-容器必须非空"><a href="#（1）T-get-：要求-Optional-容器必须非空" class="headerlink" title="（1）T get()  ：要求 Optional 容器必须非空"></a>（1）T get()  ：要求 Optional 容器必须非空</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test04</span><span class="params">()</span></span>&#123;</span><br><span class="line">    String str = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">    Optional&lt;String&gt; opt = Optional.of(str);</span><br><span class="line">    System.out.println(opt.get());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="（2）T-orElse-T-other-："><a href="#（2）T-orElse-T-other-：" class="headerlink" title="（2）T orElse(T other)  ："></a>（2）T orElse(T other)  ：</h5><p>orElse(T other) 与 ofNullable(T value)配合使用，</p>
<p>如果 Optional 容器中非空，就返回所包装值，如果为空，就用 orElse(T other)， other 是指定的默认值（备胎）代替</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test05</span><span class="params">()</span></span>&#123;</span><br><span class="line">    String str = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">    Optional&lt;String&gt; opt = Optional.ofNullable(str);</span><br><span class="line">    String string = opt.orElse(<span class="string">&quot;atguigu&quot;</span>);</span><br><span class="line">    System.out.println(string);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="（3）T-orElseGet-Supplier-lt-extends-T-gt-other-："><a href="#（3）T-orElseGet-Supplier-lt-extends-T-gt-other-：" class="headerlink" title="（3）T orElseGet(Supplier&lt;? extends T&gt; other)  ："></a>（3）T orElseGet(Supplier&lt;? extends T&gt; other)  ：</h5><p>如果 Optional 容器中非空，就返回所包装值，如果为空，就用 Supplier 接口的 Lambda 表达式提供的值代替</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test06</span><span class="params">()</span></span>&#123;</span><br><span class="line">    String str = <span class="keyword">null</span>;</span><br><span class="line">    Optional&lt;String&gt; opt = Optional.ofNullable(str);</span><br><span class="line">    String string = opt.orElseGet(String::<span class="keyword">new</span>);</span><br><span class="line">    System.out.println(string);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="（4）-lt-X-extends-Throwable-gt-T-orElseThrow-Supplier-lt-extends-X-gt-exceptionSupplier"><a href="#（4）-lt-X-extends-Throwable-gt-T-orElseThrow-Supplier-lt-extends-X-gt-exceptionSupplier" class="headerlink" title="（4）&lt;X extends Throwable&gt; T orElseThrow(Supplier&lt;? extends X&gt; exceptionSupplier)"></a>（4）<code>&lt;X extends Throwable&gt;</code> T orElseThrow(Supplier&lt;? extends X&gt; exceptionSupplier)</h5><p>如果 Optional 容器中非空，就返回所包装值，如果为空，就抛出你指定的异常类型代替原来的 NoSuchElementException</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test07</span><span class="params">()</span></span>&#123;</span><br><span class="line">    String str = <span class="keyword">null</span>;</span><br><span class="line">    Optional&lt;String&gt; opt = Optional.ofNullable(str);</span><br><span class="line">    String string = opt.orElseThrow(()-&gt;<span class="keyword">new</span> RuntimeException(<span class="string">&quot;值不存在&quot;</span>));</span><br><span class="line">    System.out.println(string);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>3、其他方法</p>
<p>（1）boolean isPresent()  ：判断 Optional 容器中是否有值</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test08</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Optional&lt;String&gt; op = Optional.of(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">    <span class="keyword">boolean</span> present = op.isPresent();</span><br><span class="line">    System.out.println(present);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>（2）void ifPresent(Consumer&lt;? super T&gt; consumer) ：</p>
<p>判断 Optional 容器中的值是否存在，如果存在，就对它进行 Consumer 指定的操作，如果不存在就不做</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test09</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Optional&lt;String&gt; op = Optional.of(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">    op.ifPresent(s -&gt; System.out.println(<span class="string">&quot;存在值&quot;</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>（3）<code>&lt;U&gt; Optional&lt;U&gt;</code> map(Function&lt;? super T，? extends U&gt; mapper)  </p>
<p>判断 Optional 容器中的值是否存在，如果存在，就对它进行 Function 接口指定的操作，如果不存在就不做</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test10</span><span class="params">()</span></span>&#123;</span><br><span class="line">    String str = <span class="string">&quot;Hello&quot;</span>;</span><br><span class="line">    Optional&lt;String&gt; opt = Optional.ofNullable(str);</span><br><span class="line">    <span class="comment">// 判断是否是纯字母单词，如果是，转为大写，否则保持不变</span></span><br><span class="line">    String result = opt.filter(s-&gt;s.matches(<span class="string">&quot;[a-zA-Z]+&quot;</span>)).</span><br><span class="line">        map(s -&gt; s.toLowerCase()).</span><br><span class="line">        orElse(str);</span><br><span class="line">    System.out.println(result);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-练习"><a href="#2-练习" class="headerlink" title="2 练习"></a>2 练习</h3><h4 id="2-1-练习-1"><a href="#2-1-练习-1" class="headerlink" title="2.1 练习 1"></a>2.1 练习 1</h4><p>案例：</p>
<p>（1）声明一个 Girl 类型，包含姓名（String）属性</p>
<p>（2）声明一个 Boy 类型，包含姓名（String），女朋友（Girl）属性</p>
<p>（3）在测试类中，创建一个 Boy 对象，并</p>
<p>如果他有女朋友，显示他女朋友名称；</p>
<p>如果他没有女朋友，他的女朋友默认为 “嫦娥”，即只能欣赏“嫦娥” 了</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Girl</span></span>&#123;</span><br><span class="line">	<span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Girl</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">super</span>();</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> name;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="string">&quot;Girl [name=&quot;</span> + name + <span class="string">&quot;]&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Boy</span></span>&#123;</span><br><span class="line">	<span class="keyword">private</span> String name;</span><br><span class="line">	<span class="keyword">private</span> Girl girlFriend;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Boy</span><span class="params">(String name， Girl girlFriend)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">super</span>();</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">		<span class="keyword">this</span>.girlFriend = girlFriend;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> Girl <span class="title">getGirlFriend</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> girlFriend;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setGirlFriend</span><span class="params">(Girl girlFriend)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.girlFriend = girlFriend;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="string">&quot;Boy [name=&quot;</span> + name + <span class="string">&quot;， girlFriend=&quot;</span> + girlFriend + <span class="string">&quot;]&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>测试类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line"><span class="comment">//		Boy boy = new Boy(&quot;张三&quot;，null);</span></span><br><span class="line">		Boy boy = <span class="keyword">new</span> Boy(<span class="string">&quot;张三&quot;</span>，<span class="keyword">new</span> Girl(<span class="string">&quot;翠翠&quot;</span>));</span><br><span class="line">		Optional&lt;Girl&gt; grilFriend = Optional.ofNullable(boy.getGirlFriend());</span><br><span class="line">		Optional.of(grilFriend.orElse(<span class="keyword">new</span> Girl(<span class="string">&quot;嫦娥&quot;</span>))).ifPresent(g-&gt;System.out.println(g));</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure>

<h4 id="2-2-练习-2"><a href="#2-2-练习-2" class="headerlink" title="2.2 练习 2"></a>2.2 练习 2</h4><p>案例：</p>
<p>（1）声明学生类，包含姓名和年龄</p>
<p>（2）添加几个学生对象到一个 <code>ArrayList&lt;Student&gt;</code> 集合中</p>
<p>（3）对集合中的学生进行操作，找出年龄大于 30 岁的，并取出第一个学生，如果没有这样的学生，用无参构造 new 一个学生对象，打印学生信息</p>
<p>学生类示例代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span></span>&#123;</span><br><span class="line">	<span class="keyword">private</span> String name;</span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">(String name， <span class="keyword">int</span> age)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">super</span>();</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">		<span class="keyword">this</span>.age = age;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">super</span>();</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getAge</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> age;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setAge</span><span class="params">(<span class="keyword">int</span> age)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.age = age;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="string">&quot;Student [name=&quot;</span> + name + <span class="string">&quot;， age=&quot;</span> + age + <span class="string">&quot;]&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>测试类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test1</span><span class="params">()</span></span>&#123;</span><br><span class="line">    ArrayList&lt;Student&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    list.add(<span class="keyword">new</span> Student(<span class="string">&quot;张三&quot;</span>， <span class="number">23</span>));</span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 取出流中第一个年龄大于 30 岁的学生的年龄，并打印它的年龄，如果没有，用无参构造创建一个学生对象</span></span><br><span class="line">    Student stu = list.stream()</span><br><span class="line">        .filter(s -&gt; s.getAge() &gt; <span class="number">30</span>)</span><br><span class="line">        .findFirst().orElse(<span class="keyword">new</span> Student());</span><br><span class="line">    System.out.println(<span class="string">&quot;学生的年龄：&quot;</span> + stu.getAge());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="第五章-接口的新特性"><a href="#第五章-接口的新特性" class="headerlink" title="第五章 接口的新特性"></a>第五章 接口的新特性</h2><h3 id="1-jdk8-之前的接口"><a href="#1-jdk8-之前的接口" class="headerlink" title="1 jdk8 之前的接口"></a>1 jdk8 之前的接口</h3><p>在 jdk8 之前，interface 之中可以定义变量和方法，变量必须是 public、static、final 的，方法必须是 public、abstract 的。由于这些修饰符都是默认的以下写法等价 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">JDK8BeforeInterface</span> </span>&#123;  </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> field1 = <span class="number">0</span>;  </span><br><span class="line">  </span><br><span class="line">    <span class="keyword">int</span> field2 = <span class="number">0</span>;  </span><br><span class="line">  </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title">method1</span><span class="params">(<span class="keyword">int</span> a)</span> <span class="keyword">throws</span> Exception</span>;  </span><br><span class="line">  </span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">method2</span><span class="params">(<span class="keyword">int</span> a)</span> <span class="keyword">throws</span> Exception</span>;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-jdk8-之后的接口"><a href="#2-jdk8-之后的接口" class="headerlink" title="2 jdk8 之后的接口"></a>2 jdk8 之后的接口</h3><p> JDK8 及以后，允许我们在接口中定义 static 方法和 default 方法</p>
<ul>
<li>接口中定义的静态 static 方法只能通过接口名直接调用，default 的方法需要用接口的实现类的对象来调用</li>
<li>接口中的 static 和 default 方法可以有函数体，其实现类不必要重写（可以不重写，也可重写）</li>
<li>其他的非 static 和非 default 的都是抽象方法，没有函数体，实现类必须重写所有的抽象方法</li>
<li>如果子类（或实现类）继承的父类和其实现的接口定义了同名同参的方法，并且接口中的方法为 default 方法（都有函数体），那么该子类的对象调用该方法时（在子类没有重写该方法的情况下），默认是父类的方法（类优先性）</li>
<li>如果类实现了多个接口，而且多个接口中定义了同名同参数的 default 方法（有函数体），在该类没有重写的情况下，就会报错（接口冲突）。如果想解决这个问题，就必须在该类中重写此方法。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">JDK8Interface</span> </span>&#123;  </span><br><span class="line">  </span><br><span class="line">    <span class="comment">// static 修饰符定义静态方法  </span></span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">staticMethod</span><span class="params">()</span> </span>&#123;  </span><br><span class="line">        System.out.println(<span class="string">&quot;接口中的静态方法&quot;</span>);  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">    <span class="comment">// default 修饰符定义默认方法  </span></span><br><span class="line">    <span class="function"><span class="keyword">default</span> <span class="keyword">void</span> <span class="title">defaultMethod</span><span class="params">()</span> </span>&#123;  </span><br><span class="line">        System.out.println(<span class="string">&quot;接口中的默认方法&quot;</span>);  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;  </span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JDK8InterfaceImpl</span> <span class="keyword">implements</span> <span class="title">JDK8Interface</span> </span>&#123;  </span><br><span class="line">    <span class="comment">// 实现接口后，因为默认方法不是抽象方法，所以可以不重写，但是如果开发需要，也可以重写  </span></span><br><span class="line">&#125;  </span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;  </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;  </span><br><span class="line">        <span class="comment">// static 方法必须通过接口类调用  </span></span><br><span class="line">        JDK8Interface.staticMethod();  </span><br><span class="line">  </span><br><span class="line">        <span class="comment">// default 方法必须通过实现类的对象调用  </span></span><br><span class="line">        <span class="keyword">new</span> JDK8InterfaceImpl().defaultMethod();  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;  </span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AnotherJDK8InterfaceImpl</span> <span class="keyword">implements</span> <span class="title">JDK8Interface</span> </span>&#123;  </span><br><span class="line">    <span class="comment">// 当然如果接口中的默认方法不能满足某个实现类需要，那么实现类可以覆盖默认方法。  </span></span><br><span class="line">    <span class="comment">// 签名跟接口 default 方法一致，但是不能再加 default 修饰符  </span></span><br><span class="line">    <span class="meta">@Override</span>  </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">defaultMethod</span><span class="params">()</span> </span>&#123;  </span><br><span class="line">        System.out.println(<span class="string">&quot;接口实现类覆盖了接口中的 default&quot;</span>);  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure>

</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">Steve</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://steve6636.gitee.io/2022/03/06/Junit&amp;jdk8%E6%96%B0%E7%89%B9%E6%80%A7/">https://steve6636.gitee.io/2022/03/06/Junit&amp;jdk8%E6%96%B0%E7%89%B9%E6%80%A7/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://steve6636.gitee.io" target="_blank">小波的博客</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/JAVA/">JAVA</a></div><div class="post_share"><div class="social-share" data-image="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.05sun.com%2Fup%2F2006%2F2020611101156542640.png&amp;refer=http%3A%2F%2Fimg.05sun.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1649170568&amp;t=1d3529a6cb00dac37673cce4473d9a89" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button button--animated"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="/img/wechat.jpg" target="_blank"><img class="post-qr-code-img" data-lazy-src="/img/wechat.jpg" alt="wechat"/></a><div class="post-qr-code-desc">wechat</div></li><li class="reward-item"><a href="/img/alipay.jpg" target="_blank"><img class="post-qr-code-img" data-lazy-src="/img/alipay.jpg" alt="alipay"/></a><div class="post-qr-code-desc">alipay</div></li></ul></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2022/03/06/Git-study/"><img class="prev-cover" data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20220306225241.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">git 笔记.md</div></div></a></div><div class="next-post pull-right"><a href="/2022/03/06/Docker%20%E7%AC%94%E8%AE%B0_20210404/"><img class="next-cover" data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20220306223850.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">Docker 笔记.md</div></div></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="card-info-avatar is-center"><img class="avatar-img" data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20210327175316.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/><div class="author-info__name">Steve</div><div class="author-info__description">路漫漫其修远兮，吾将上下而求索</div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">26</div></a></div><div class="card-info-data-item is-center"><a href="/tags/"><div class="headline">标签</div><div class="length-num">11</div></a></div><div class="card-info-data-item is-center"><a href="/categories/"><div class="headline">分类</div><div class="length-num">9</div></a></div></div><a class="button--animated" id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/forkiller"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/forkiller" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="mailto:1518109600@qq.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn card-announcement-animation"></i><span>公告</span></div><div class="announcement_content">冷灯看剑，剑上几番功名？炉香无须计苍生，纵一川烟逝，万丈云埋，孤阳还照古陵</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#Junit-amp-jdk8-%E6%96%B0%E7%89%B9%E6%80%A7"><span class="toc-text">Junit&amp;jdk8 新特性</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AC%AC%E4%B8%80%E7%AB%A0-Junit"><span class="toc-text">第一章 Junit</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E5%AD%A6%E4%B9%A0%E7%9B%AE%E6%A0%87"><span class="toc-text">1. 学习目标</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E5%86%85%E5%AE%B9%E8%AE%B2%E8%A7%A3"><span class="toc-text">2. 内容讲解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-Junit-%E6%98%AF%E4%BB%80%E4%B9%88"><span class="toc-text">2.1 Junit 是什么</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E6%A6%82%E5%BF%B5"><span class="toc-text">2.2 单元测试概念</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3-Junit-%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E6%A1%86%E6%9E%B6%E7%9A%84%E4%BD%9C%E7%94%A8"><span class="toc-text">2.3 Junit 单元测试框架的作用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-4-Junit-%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E6%A1%86%E6%9E%B6%E7%9A%84%E4%BD%BF%E7%94%A8%E6%AD%A5%E9%AA%A4"><span class="toc-text">2.4 Junit 单元测试框架的使用步骤</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-5-%E6%B5%8B%E8%AF%95%E6%96%B9%E6%B3%95%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9"><span class="toc-text">2.5 测试方法注意事项</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-6-%E5%A6%82%E4%BD%95%E8%BF%90%E8%A1%8C%E6%B5%8B%E8%AF%95%E6%96%B9%E6%B3%95"><span class="toc-text">2.6 如何运行测试方法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-7-%E5%A6%82%E4%BD%95%E6%9F%A5%E7%9C%8B%E6%B5%8B%E8%AF%95%E7%BB%93%E6%9E%9C"><span class="toc-text">2.7 如何查看测试结果</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-8-Junit-%E5%B8%B8%E7%94%A8%E6%B3%A8%E8%A7%A3-Junit4-xxxx-%E7%89%88%E6%9C%AC"><span class="toc-text">2.8 Junit 常用注解(Junit4.xxxx 版本)</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-9-Junit-%E5%B8%B8%E7%94%A8%E6%B3%A8%E8%A7%A3-Junit5-xxxx-%E7%89%88%E6%9C%AC"><span class="toc-text">2.9 Junit 常用注解(Junit5.xxxx 版本)</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-10-Junit-%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="toc-text">2.10 Junit 的使用</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AC%AC%E4%BA%8C%E7%AB%A0-Lambda-%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="toc-text">第二章 Lambda 表达式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E5%AD%A6%E4%B9%A0%E7%9B%AE%E6%A0%87-1"><span class="toc-text">1. 学习目标</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E5%86%85%E5%AE%B9%E8%AE%B2%E8%A7%A3-1"><span class="toc-text">2. 内容讲解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B%E7%9A%84%E4%BC%98%E5%8A%BF"><span class="toc-text">2.1 函数式编程的优势</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-1-1-%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3"><span class="toc-text">2.1.1 函数式编程思想</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-2%EF%BC%8C2-%E5%86%97%E4%BD%99%E7%9A%84%E5%8C%BF%E5%90%8D%E5%86%85%E9%83%A8%E7%B1%BB"><span class="toc-text">2.2，2 冗余的匿名内部类</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-1-3-%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3%E8%BD%AC%E6%8D%A2"><span class="toc-text">2.1.3 编程思想转换</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-1-4-%E4%BD%93%E9%AA%8C-Lambda-%E7%9A%84%E6%9B%B4%E4%BC%98%E5%86%99%E6%B3%95"><span class="toc-text">2.1.4 体验 Lambda 的更优写法</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.2 函数式接口</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-2-1-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.2.1 自定义函数式接口</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-2-2-%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%88%86%E7%B1%BB"><span class="toc-text">2.2.2 函数式接口的分类</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#2-2-2-1-%E6%B6%88%E8%B4%B9%E5%9E%8B%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.2.2.1 消费型接口</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#2-2-2-2-%E4%BE%9B%E7%BB%99%E5%9E%8B%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.2.2.2 供给型接口</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#2-2-2-3-%E6%96%AD%E8%A8%80%E5%9E%8B%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.2.2.3 断言型接口</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#2-2-2-4-%E5%8A%9F%E8%83%BD%E5%9E%8B%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.2.2.4 功能型接口</span></a></li></ol></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3-Lambda-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E6%B3%95"><span class="toc-text">2.3 Lambda 表达式语法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-4-Lambda-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%BB%83%E4%B9%A0"><span class="toc-text">2.4 Lambda 表达式练习</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-1-%E6%97%A0%E5%8F%82%E6%97%A0%E8%BF%94%E5%9B%9E%E5%80%BC%E5%BD%A2%E5%BC%8F"><span class="toc-text">2.4.1 无参无返回值形式</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-2-%E6%B6%88%E8%B4%B9%E5%9E%8B%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.4.2 消费型接口</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-3-%E4%BE%9B%E7%BB%99%E5%9E%8B%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.4.3 供给型接口</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-4-%E5%8A%9F%E8%83%BD%E5%9E%8B%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.4.4 功能型接口</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-5-%E5%88%A4%E6%96%AD%E5%9E%8B%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.4.5 判断型接口</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-6-%E5%88%A4%E6%96%AD%E5%9E%8B%E6%8E%A5%E5%8F%A3"><span class="toc-text">2.4.6 判断型接口</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-5-%E6%96%B9%E6%B3%95%E5%BC%95%E7%94%A8%E4%B8%8E%E6%9E%84%E9%80%A0%E5%99%A8%E5%BC%95%E7%94%A8"><span class="toc-text">2.5 方法引用与构造器引用</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-1-%E6%96%B9%E6%B3%95%E5%BC%95%E7%94%A8"><span class="toc-text">2.5.1 方法引用</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-2-%E6%9E%84%E9%80%A0%E5%99%A8%E5%BC%95%E7%94%A8"><span class="toc-text">2.5.2 构造器引用</span></a></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AC%AC%E4%B8%89%E7%AB%A0-Stream-%E6%B5%81"><span class="toc-text">第三章 Stream 流</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E5%AD%A6%E4%B9%A0%E7%9B%AE%E6%A0%87-2"><span class="toc-text">1. 学习目标</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E5%86%85%E5%AE%B9%E8%AE%B2%E8%A7%A3-2"><span class="toc-text">2. 内容讲解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-Stream-%E6%B5%81%E7%9A%84%E4%BC%98%E5%8A%BF"><span class="toc-text">2.1 Stream 流的优势</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-Stream-%E6%B5%81%E7%9A%84%E4%BD%BF%E7%94%A8%E6%AD%A5%E9%AA%A4"><span class="toc-text">2.2 Stream 流的使用步骤</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3-%E5%88%9B%E5%BB%BA-Stream"><span class="toc-text">2.3 创建 Stream</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-3-1-%E5%88%9B%E5%BB%BA-Stream-%E6%96%B9%E5%BC%8F%E4%B8%80%EF%BC%9A%E9%80%9A%E8%BF%87%E9%9B%86%E5%90%88"><span class="toc-text">2.3.1 创建 Stream 方式一：通过集合</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-3-2-%E5%88%9B%E5%BB%BA-Stream-%E6%96%B9%E5%BC%8F%E4%BA%8C%EF%BC%9A%E9%80%9A%E8%BF%87%E6%95%B0%E7%BB%84"><span class="toc-text">2.3.2 创建 Stream 方式二：通过数组</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-3-3-%E5%88%9B%E5%BB%BA-Stream-%E6%96%B9%E5%BC%8F%E4%B8%89%EF%BC%9A%E9%80%9A%E8%BF%87-Stream-%E7%9A%84-of"><span class="toc-text">2.3.3 创建 Stream 方式三：通过 Stream 的 of()</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-2-4-%E5%88%9B%E5%BB%BA-Stream-%E6%96%B9%E5%BC%8F%E5%9B%9B%EF%BC%9A%E5%88%9B%E5%BB%BA%E6%97%A0%E9%99%90%E6%B5%81"><span class="toc-text">2.2.4 创建 Stream 方式四：创建无限流</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-4-%E4%B8%AD%E9%97%B4%E6%93%8D%E4%BD%9C"><span class="toc-text">2.4  中间操作</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-1-filer-%E8%BF%87%E6%BB%A4"><span class="toc-text">2.4.1 filer 过滤</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-2-distinct-%E5%8E%BB%E9%87%8D"><span class="toc-text">2.4.2 distinct 去重</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-3-limit-%E6%88%AA%E6%96%AD"><span class="toc-text">2.4.3 limit 截断</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-4-skip-%E8%B7%B3%E8%BF%87"><span class="toc-text">2.4.4 skip 跳过</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-5-peek-%E5%AF%B9%E6%AF%8F%E4%B8%AA%E5%85%83%E7%B4%A0%E8%BF%9B%E8%A1%8C-Lambda-%E6%93%8D%E4%BD%9C"><span class="toc-text">2.4.5 peek 对每个元素进行 Lambda 操作</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-6-sorted-%E6%8E%92%E5%BA%8F"><span class="toc-text">2.4.6 sorted 排序</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-7-map-%E6%98%A0%E5%B0%84%E6%88%90%E6%96%B0%E5%85%83%E7%B4%A0"><span class="toc-text">2.4.7 map 映射成新元素</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4-9-%E6%89%80%E6%9C%89%E4%B8%AD%E9%97%B4%E6%93%8D%E4%BD%9C%E6%96%B9%E6%B3%95%E5%88%97%E8%A1%A8"><span class="toc-text">2.4.9 所有中间操作方法列表</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-5-%E7%BB%88%E7%BB%93%E6%93%8D%E4%BD%9C"><span class="toc-text">2.5  终结操作</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-1-forEach-%E8%BF%AD%E4%BB%A3"><span class="toc-text">2.5.1 forEach 迭代</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-2-count-%E8%BF%94%E5%9B%9E%E6%B5%81%E4%B8%AD%E5%85%83%E7%B4%A0%E6%80%BB%E6%95%B0"><span class="toc-text">2.5.2 count 返回流中元素总数</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-3-allMatch-%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%8C%B9%E9%85%8D%E6%89%80%E6%9C%89%E5%85%83%E7%B4%A0"><span class="toc-text">2.5.3 allMatch 检查是否匹配所有元素</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-4-anyMatch-%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E8%87%B3%E5%B0%91%E5%8C%B9%E9%85%8D%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0"><span class="toc-text">2.5.4 anyMatch 检查是否至少匹配一个元素</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-5-findFirst-%E8%BF%94%E5%9B%9E%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0"><span class="toc-text">2.5.5 findFirst 返回第一个元素</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-6-max-%E8%BF%94%E5%9B%9E%E6%B5%81%E4%B8%AD%E6%9C%80%E5%A4%A7%E5%80%BC"><span class="toc-text">2.5.6 max 返回流中最大值</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-7-reduce-%E5%8F%AF%E4%BB%A5%E5%B0%86%E6%B5%81%E4%B8%AD%E5%85%83%E7%B4%A0%E5%8F%8D%E5%A4%8D%E7%BB%93%E5%90%88%E6%93%8D%E4%BD%9C%E8%B5%B7%E6%9D%A5%EF%BC%8C%E5%BE%97%E5%88%B0%E4%B8%80%E4%B8%AA%E5%80%BC"><span class="toc-text">2.5.7 reduce 可以将流中元素反复结合操作起来，得到一个值</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-8-collect-%E5%B0%86%E6%B5%81%E8%BD%AC%E6%8D%A2%E4%B8%BA%E5%85%B6%E4%BB%96%E5%BD%A2%E5%BC%8F-%E5%BE%88%E9%87%8D%E8%A6%81"><span class="toc-text">2.5.8 collect 将流转换为其他形式(很重要)</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-5-9-%E6%89%80%E6%9C%89%E7%BB%88%E7%BB%93%E6%93%8D%E4%BD%9C%E7%9A%84%E6%96%B9%E6%B3%95%E5%88%97%E8%A1%A8"><span class="toc-text">2.5.9 所有终结操作的方法列表</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-6-%E7%BB%83%E4%B9%A0"><span class="toc-text">2.6 练习</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AC%AC%E5%9B%9B%E7%AB%A0-Optional-%E7%B1%BB"><span class="toc-text">第四章 Optional 类</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-API"><span class="toc-text">1 API</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1-%E5%88%9B%E5%BB%BA-Optional-%E5%AF%B9%E8%B1%A1"><span class="toc-text">1.1 创建 Optional 对象</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-2-%E4%BB%8E-Optional-%E5%AE%B9%E5%99%A8%E4%B8%AD%E5%8F%96%E5%87%BA%E6%89%80%E5%8C%85%E8%A3%85%E7%9A%84%E5%AF%B9%E8%B1%A1"><span class="toc-text">2.2 从 Optional 容器中取出所包装的对象</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%EF%BC%881%EF%BC%89T-get-%EF%BC%9A%E8%A6%81%E6%B1%82-Optional-%E5%AE%B9%E5%99%A8%E5%BF%85%E9%A1%BB%E9%9D%9E%E7%A9%BA"><span class="toc-text">（1）T get()  ：要求 Optional 容器必须非空</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%EF%BC%882%EF%BC%89T-orElse-T-other-%EF%BC%9A"><span class="toc-text">（2）T orElse(T other)  ：</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%EF%BC%883%EF%BC%89T-orElseGet-Supplier-lt-extends-T-gt-other-%EF%BC%9A"><span class="toc-text">（3）T orElseGet(Supplier&lt;? extends T&gt; other)  ：</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%EF%BC%884%EF%BC%89-lt-X-extends-Throwable-gt-T-orElseThrow-Supplier-lt-extends-X-gt-exceptionSupplier"><span class="toc-text">（4）&lt;X extends Throwable&gt; T orElseThrow(Supplier&lt;? extends X&gt; exceptionSupplier)</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E7%BB%83%E4%B9%A0"><span class="toc-text">2 练习</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-%E7%BB%83%E4%B9%A0-1"><span class="toc-text">2.1 练习 1</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-%E7%BB%83%E4%B9%A0-2"><span class="toc-text">2.2 练习 2</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AC%AC%E4%BA%94%E7%AB%A0-%E6%8E%A5%E5%8F%A3%E7%9A%84%E6%96%B0%E7%89%B9%E6%80%A7"><span class="toc-text">第五章 接口的新特性</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-jdk8-%E4%B9%8B%E5%89%8D%E7%9A%84%E6%8E%A5%E5%8F%A3"><span class="toc-text">1 jdk8 之前的接口</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-jdk8-%E4%B9%8B%E5%90%8E%E7%9A%84%E6%8E%A5%E5%8F%A3"><span class="toc-text">2 jdk8 之后的接口</span></a></li></ol></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2022/03/06/Mysql%E7%9A%84%E4%BC%98%E5%8C%96-%E8%87%AA%E6%88%91%E6%8F%8F%E8%BF%B0/" title="MySQL 的优化.md"><img data-lazy-src="https://img2.baidu.com/it/u=1814268193,3619863984&amp;fm=253&amp;fmt=auto&amp;app=138&amp;f=JPEG?w=632&amp;h=500" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="MySQL 的优化.md"/></a><div class="content"><a class="title" href="/2022/03/06/Mysql%E7%9A%84%E4%BC%98%E5%8C%96-%E8%87%AA%E6%88%91%E6%8F%8F%E8%BF%B0/" title="MySQL 的优化.md">MySQL 的优化.md</a><time datetime="2022-03-06T14:54:18.000Z" title="发表于 2022-03-06 22:54:18">2022-03-06</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/03/06/MySQL%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD%E5%91%BD%E4%BB%A4-20210722/" title="MySQL 数据库备份命令.md"><img data-lazy-src="https://img2.baidu.com/it/u=1814268193,3619863984&amp;fm=253&amp;fmt=auto&amp;app=138&amp;f=JPEG?w=632&amp;h=500" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="MySQL 数据库备份命令.md"/></a><div class="content"><a class="title" href="/2022/03/06/MySQL%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD%E5%91%BD%E4%BB%A4-20210722/" title="MySQL 数据库备份命令.md">MySQL 数据库备份命令.md</a><time datetime="2022-03-06T14:47:18.000Z" title="发表于 2022-03-06 22:47:18">2022-03-06</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/03/06/Git-study/" title="git 笔记.md"><img data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20220306225241.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="git 笔记.md"/></a><div class="content"><a class="title" href="/2022/03/06/Git-study/" title="git 笔记.md">git 笔记.md</a><time datetime="2022-03-06T14:47:18.000Z" title="发表于 2022-03-06 22:47:18">2022-03-06</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/03/06/Junit&amp;jdk8%E6%96%B0%E7%89%B9%E6%80%A7/" title="jdk8 新特性.md"><img data-lazy-src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.05sun.com%2Fup%2F2006%2F2020611101156542640.png&amp;refer=http%3A%2F%2Fimg.05sun.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1649170568&amp;t=1d3529a6cb00dac37673cce4473d9a89" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="jdk8 新特性.md"/></a><div class="content"><a class="title" href="/2022/03/06/Junit&amp;jdk8%E6%96%B0%E7%89%B9%E6%80%A7/" title="jdk8 新特性.md">jdk8 新特性.md</a><time datetime="2022-03-06T14:47:18.000Z" title="发表于 2022-03-06 22:47:18">2022-03-06</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/03/06/Docker%20%E7%AC%94%E8%AE%B0_20210404/" title="Docker 笔记.md"><img data-lazy-src="https://gitee.com/forkiller/picture/raw/master/img/20220306223850.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Docker 笔记.md"/></a><div class="content"><a class="title" href="/2022/03/06/Docker%20%E7%AC%94%E8%AE%B0_20210404/" title="Docker 笔记.md">Docker 笔记.md</a><time datetime="2022-03-06T14:29:58.000Z" title="发表于 2022-03-06 22:29:58">2022-03-06</time></div></div></div></div></div></div></main><footer id="footer" style="background-image: url('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.05sun.com%2Fup%2F2006%2F2020611101156542640.png&amp;refer=http%3A%2F%2Fimg.05sun.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1649170568&amp;t=1d3529a6cb00dac37673cce4473d9a89')"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2022 By Steve</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="font-plus" type="button" title="放大字体"><i class="fas fa-plus"></i></button><button id="font-minus" type="button" title="缩小字体"><i class="fas fa-minus"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="local-search"><div class="search-dialog"><div class="search-dialog__title" id="local-search-title">本地搜索</div><div id="local-input-panel"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div></div><hr/><div id="local-search-results"></div><span class="search-close-button"><i class="fas fa-times"></i></span></div><div id="search-mask"></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/medium-zoom/dist/medium-zoom.min.js"></script><script src="https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script>function panguFn () {
  if (typeof pangu === 'object') pangu.autoSpacingPage()
  else {
    getScript('https://cdn.jsdelivr.net/npm/pangu/dist/browser/pangu.min.js')
      .then(() => {
        pangu.autoSpacingPage()
      })
  }
}

function panguInit () {
  if (false){
    GLOBAL_CONFIG_SITE.isPost && panguFn()
  } else {
    panguFn()
  }
}

document.addEventListener('DOMContentLoaded', panguInit)</script><script src="/js/search/local-search.js"></script><div class="js-pjax"></div><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/activate-power-mode.min.js"></script><script>POWERMODE.colorful = true;
POWERMODE.shake = true;
POWERMODE.mobile = true;
document.body.addEventListener('input', POWERMODE);
</script><script id="click-heart" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-heart.min.js" async="async" mobile="true"></script><script src="https://cdn.jsdelivr.net/npm/pjax/pjax.min.js"></script><script>let pjaxSelectors = [
  'title',
  '#config-diff',
  '#body-wrap',
  '#rightside-config-hide',
  '#rightside-config-show',
  '.js-pjax'
]

if (false) {
  pjaxSelectors.unshift('meta[property="og:image"]', 'meta[property="og:title"]', 'meta[property="og:url"]')
}

var pjax = new Pjax({
  elements: 'a:not([target="_blank"])',
  selectors: pjaxSelectors,
  cacheBust: false,
  analytics: false,
  scrollRestoration: false
})

document.addEventListener('pjax:complete', function () {
  window.refreshFn()

  document.querySelectorAll('script[data-pjax]').forEach(item => {
    const newScript = document.createElement('script')
    const content = item.text || item.textContent || item.innerHTML || ""
    Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
    newScript.appendChild(document.createTextNode(content))
    item.parentNode.replaceChild(newScript, item)
  })

  GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update()

  typeof chatBtnFn === 'function' && chatBtnFn()
  typeof panguInit === 'function' && panguInit()

  if (typeof gtag === 'function') {
    gtag('config', '', {'page_path': window.location.pathname});
  }

  typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()

  // Analytics
  if (false) {
    MtaH5.pgv()
  }

  // prismjs
  typeof Prism === 'object' && Prism.highlightAll()

  typeof preloader === 'object' && preloader.endLoading()
})


document.addEventListener('pjax:send', function () {
  typeof preloader === 'object' && preloader.initLoading()
  
  if (window.aplayers) {
    for (let i = 0; i < window.aplayers.length; i++) {
      if (!window.aplayers[i].options.fixed) {
        window.aplayers[i].destroy()
      }
    }
  }

  typeof typed === 'object' && typed.destroy()

  //reset readmode
  const $bodyClassList = document.body.classList
  $bodyClassList.contains('read-mode') && $bodyClassList.remove('read-mode')

})

document.addEventListener('pjax:error', (e) => {
  if (e.request.status === 404) {
    pjax.loadUrl('/404.html')
  }
})</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>